├── .gitignore
├── LICENSE
├── README.md
├── assets
├── debugbar.css
├── debugbar.js
├── index.css
├── openhandler.css
├── openhandler.js
├── vendor
│ ├── font-awesome
│ │ ├── css
│ │ │ └── font-awesome.min.css
│ │ └── fonts
│ │ │ ├── FontAwesome.otf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.svg
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ ├── fontawesome-webfont.woff
│ │ │ └── fontawesome-webfont.woff2
│ ├── highlightjs
│ │ ├── highlight.pack.js
│ │ └── styles
│ │ │ └── github.css
│ └── jquery
│ │ └── dist
│ │ └── jquery.min.js
├── widgets.css
├── widgets.js
└── widgets
│ ├── mails
│ ├── widget.css
│ └── widget.js
│ ├── sqlqueries
│ ├── widget.css
│ └── widget.js
│ └── templates
│ ├── widget.css
│ └── widget.js
├── composer.json
├── composer.lock
├── index.php
├── snippets
└── debugbar.php
└── src
├── DataCollector
├── EventCollector.php
├── FileCollector.php
└── VariableCollector.php
├── Debugbar.php
├── Logger.php
└── LoggerInterface.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | node_modules/
3 | !assets/vendor/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Vincent Laurent Riva
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP Debug Bar for KirbyCMS
2 |
3 | 
4 |
5 | ## ✨ Features
6 |
7 | - Integration of [PHP Debug Bar](https://github.com/maximebf/php-debugbar)
8 | - Easy log messages
9 | - Preview configuration, hooks called, files, page variables, requests & exceptions
10 | - More soon 👀 ...
11 |
12 | ## 🔌 Installation
13 |
14 | ⚠️ This plugin uses the Symfony VarDumper package, which conflicts with the KirbyCMS dump function. To use this plugin, you must imperatively change the `index.php` file at the root by this content:
15 |
16 | ```php
17 | render();
24 | ```
25 |
26 | ### Composer (highly recommended)
27 |
28 | composer require treast/kirby-debugbar
29 |
30 | ### Git submodule
31 |
32 | git submodule add https://github.com/Treast/kirby-debugbar.git site/plugins/debugbar
33 |
34 | ### Manual
35 |
36 | Download this [zip](https://github.com/Treast/kirby-debugbar/archive/refs/heads/main.zip) and unzip it in `site/plugins/debugbar`.
37 |
38 | ## 💻 Usage
39 |
40 | Add this snippet at the bottom of your footer & enjoy !
41 |
42 | = snippet('debugbar') ?>
43 |
44 | ### How to log ?
45 |
46 | ```php
47 | $site->logger()->debug('This is a debug');
48 | $site->logger()->emergency('This is an emergency');
49 | $site->logger()->error('This is an error');
50 | $site->logger()->critical('This is a critical');
51 | $site->logger()->info('This is an info');
52 | $site->logger()->warning('This is a warning');
53 | $site->logger()->alert('This is an alert');
54 | $site->logger()->notice('This is a notice');
55 | $site->logger()->log('debug', 'This is also a debug');
56 | // Or you can chain with the ->log() function
57 | $site->log()->title()->log();
58 | $page->children()->log()->first()->log();
59 | ```
60 |
61 | ### Options
62 |
63 | #### Explanations
64 |
65 | | Option name | Default | Type | Description |
66 | | -------------------------------- | ------- | --------- | ------------------------------------------------------------------ |
67 | | `treast.debugbar.force` | `false` | `boolean` | If enabled, will display the debug bar even with `debug === false` |
68 | | `treast.debugbar.tabs.logs` | `true` | `boolean` | Show logs tab |
69 | | `treast.debugbar.tabs.config` | `true` | `boolean` | Show config tab |
70 | | `treast.debugbar.tabs.events` | `true` | `boolean` | Show events tab |
71 | | `treast.debugbar.tabs.files` | `true` | `boolean` | Show files tab |
72 | | `treast.debugbar.tabs.variables` | `true` | `boolean` | Show variables tab |
73 | | `treast.debugbar.tabs.request` | `true` | `boolean` | Show request tab |
74 | | `treast.debugbar.tabs.exception` | `true` | `boolean` | Show exceptions tab |
75 |
76 | #### config.php
77 |
78 | ```php
79 | [
83 | 'force' => false,
84 | 'tabs' => [
85 | 'logs' => true,
86 | 'config' => true,
87 | 'events' => true,
88 | 'files' => true,
89 | 'variables' => true,
90 | 'request' => true,
91 | 'exceptions' => true
92 | ]
93 | ]
94 | ];
95 | ```
96 |
97 | ## To Do
98 |
99 | - ~~Only activate plugin when `debug === true`~~
100 | - Refactoring 😮💨
101 |
102 | ## 💡 I would like XXX but it's not yet available?
103 |
104 | [Go to the issues](https://github.com/Treast/kirby-debugbar/issues) and submit your idea. If it's relevant, I might add it 🫶.
105 |
106 | ## ❤️Special Thanks
107 |
108 | - To [@maximebf](https://www.github.com/maximebf) for the base package [php-debugbar](https://github.com/maximebf/php-debugbar).
109 | - To [@barryvdh](https://www.github.com/barryvdh) for his [implementation on Laravel](https://github.com/barryvdh/laravel-debugbar).
110 | - To [@genxbe](https://www.github.com/genxbe) for his chaining methods [on his plugin](https://github.com/genxbe/kirby3-ray).
111 |
112 | ## ⚠️Warning
113 |
114 | Please note that this plugin is provided as is, without any express or implied warranty of operation. By using this plugin, you agree to do so at your own risk. I am not responsible for any direct or indirect damage resulting from the use of this plugin, including loss of data, operating errors, service interruptions, or any other consequence related to the use of this plugin.
115 |
--------------------------------------------------------------------------------
/assets/debugbar.css:
--------------------------------------------------------------------------------
1 | /* Hide debugbar when printing a page */
2 | @media print {
3 | div.phpdebugbar {
4 | display: none;
5 | }
6 | }
7 |
8 | div.phpdebugbar {
9 | position: fixed;
10 | bottom: 0;
11 | left: 0;
12 | width: 100%;
13 | border-top: 0;
14 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
15 | background: #fff;
16 | z-index: 10000;
17 | font-size: 14px;
18 | color: #000;
19 | text-align: left;
20 | line-height: 1;
21 | letter-spacing: normal;
22 | direction: ltr;
23 | }
24 |
25 | div.phpdebugbar a,
26 | div.phpdebugbar-openhandler {
27 | cursor: pointer;
28 | }
29 |
30 | div.phpdebugbar-drag-capture {
31 | position: fixed;
32 | top: 0;
33 | bottom: 0;
34 | left: 0;
35 | right: 0;
36 | z-index: 10001;
37 | background: none;
38 | display: none;
39 | cursor: ns-resize;
40 | }
41 |
42 | div.phpdebugbar-closed {
43 | width: auto;
44 | }
45 |
46 | div.phpdebugbar * {
47 | margin: 0;
48 | padding: 0;
49 | border: 0;
50 | font-weight: normal;
51 | text-decoration: none;
52 | clear: initial;
53 | width: auto;
54 | -moz-box-sizing: content-box;
55 | box-sizing: content-box;
56 | }
57 |
58 | div.phpdebugbar ol, div.phpdebugbar ul {
59 | list-style: none;
60 | }
61 |
62 | div.phpdebugbar table {
63 | border-collapse: collapse;
64 | border-spacing: 0;
65 | }
66 |
67 | div.phpdebugbar input[type='text'], div.phpdebugbar input[type='password'] {
68 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
69 | background: #fff;
70 | font-size: 14px;
71 | color: #000;
72 | border: 0;
73 | padding: 0;
74 | margin: 0;
75 | }
76 |
77 | div.phpdebugbar code, div.phpdebugbar pre, div.phpdebugbar samp {
78 | background: none;
79 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
80 | font-size: 1em;
81 | border: 0;
82 | padding: 0;
83 | margin: 0;
84 | }
85 |
86 | div.phpdebugbar code, div.phpdebugbar pre {
87 | color: #000;
88 | }
89 |
90 | div.phpdebugbar pre.sf-dump {
91 | color: #a0a000;
92 | outline: 0;
93 | }
94 |
95 | a.phpdebugbar-restore-btn {
96 | float: left;
97 | padding: 5px 8px;
98 | font-size: 14px;
99 | color: #555;
100 | text-decoration: none;
101 | border-right: 1px solid #ddd;
102 | }
103 |
104 | div.phpdebugbar-resize-handle {
105 | display: none;
106 | height: 4px;
107 | margin-top: -4px;
108 | width: 100%;
109 | background: none;
110 | border-bottom: 1px solid #ccc;
111 | cursor: ns-resize;
112 | }
113 |
114 | div.phpdebugbar-closed, div.phpdebugbar-minimized{
115 | border-top: 1px solid #ccc;
116 | }
117 | /* -------------------------------------- */
118 |
119 | a.phpdebugbar-restore-btn {
120 | background: #efefef url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2020%2020%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle%20fill%3D%22%23000%22%20cx%3D%2210%22%20cy%3D%2210%22%20r%3D%229%22%2F%3E%3Cpath%20d%3D%22M6.039%208.342c.463%200%20.772.084.927.251.154.168.191.455.11.862-.084.424-.247.727-.487.908-.241.182-.608.272-1.1.272h-.743l.456-2.293h.837zm-2.975%204.615h1.22l.29-1.457H5.62c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.13-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H4.153l-1.089%205.479zM9.235%206.02h1.21l-.289%201.458h1.079c.679%200%201.147.115%201.405.347.258.231.335.607.232%201.125l-.507%202.55h-1.23l.481-2.424c.055-.276.035-.464-.06-.565-.095-.1-.298-.15-.608-.15H9.98L9.356%2011.5h-1.21l1.089-5.48M15.566%208.342c.464%200%20.773.084.928.251.154.168.19.455.11.862-.084.424-.247.727-.488.908-.24.182-.607.272-1.1.272h-.742l.456-2.293h.836zm-2.974%204.615h1.22l.29-1.457h1.046c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.129-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H13.68l-1.089%205.479z%22%20fill%3D%22%23FFF%22%2F%3E%3C%2Fsvg%3E) no-repeat 5px 4px / 20px 20px;
121 | }
122 | div.phpdebugbar-header {
123 | min-height: 26px;
124 | line-height: 16px;
125 | }
126 | div.phpdebugbar-header:before, div.phpdebugbar-header:after {
127 | display: table;
128 | line-height: 0;
129 | content: "";
130 | }
131 | div.phpdebugbar-header:after {
132 | clear: both;
133 | }
134 | div.phpdebugbar-header-left {
135 | float: left;
136 | }
137 | div.phpdebugbar-header-right {
138 | float: right;
139 | }
140 | div.phpdebugbar-header > div > * {
141 | padding: 5px 5px;
142 | font-size: 14px;
143 | color: #555;
144 | text-decoration: none;
145 | }
146 | div.phpdebugbar-header-left > * {
147 | float: left;
148 | }
149 | div.phpdebugbar-header-right > * {
150 | float: right;
151 | }
152 | div.phpdebugbar-header-right > select {
153 | padding: 0;
154 | }
155 |
156 | /* -------------------------------------- */
157 |
158 | span.phpdebugbar-indicator,
159 | a.phpdebugbar-indicator,
160 | a.phpdebugbar-close-btn {
161 | border-right: 1px solid #ddd;
162 | }
163 |
164 | a.phpdebugbar-tab.phpdebugbar-active {
165 | background: #ccc;
166 | color: #444;
167 | background-image: linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
168 | background-image: -o-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
169 | background-image: -moz-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
170 | background-image: -webkit-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
171 | background-image: -ms-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
172 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.41, rgb(173,173,173)), color-stop(0.71, rgb(209,209,209)));
173 | }
174 | a.phpdebugbar-tab span.phpdebugbar-badge {
175 | display: none;
176 | margin-left: 5px;
177 | font-size: 11px;
178 | line-height: 14px;
179 | padding: 0 6px;
180 | background: #ccc;
181 | border-radius: 4px;
182 | color: #555;
183 | font-weight: normal;
184 | text-shadow: none;
185 | vertical-align: middle;
186 | }
187 | a.phpdebugbar-tab i {
188 | display: none;
189 | vertical-align: middle;
190 | }
191 | a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-visible {
192 | display: inline;
193 | }
194 | a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-important {
195 | background: #ed6868;
196 | color: white;
197 | }
198 |
199 | a.phpdebugbar-close-btn, a.phpdebugbar-open-btn, a.phpdebugbar-restore-btn, a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
200 | width: 16px;
201 | height: 16px;
202 | }
203 |
204 | a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
205 | padding-right: 0 !important;
206 | }
207 |
208 | a.phpdebugbar-maximize-btn { display: none}
209 |
210 | a.phpdebugbar-minimize-btn { display: block}
211 |
212 | div.phpdebugbar-minimized a.phpdebugbar-maximize-btn { display: block}
213 |
214 | div.phpdebugbar-minimized a.phpdebugbar-minimize-btn { display: none}
215 |
216 | a.phpdebugbar-minimize-btn {
217 | 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%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
218 | }
219 |
220 | a.phpdebugbar-maximize-btn {
221 | 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%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
222 | }
223 |
224 | a.phpdebugbar-close-btn {
225 | 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%22close%22%3E%3Cpath%20d%3D%22M1490%201322q0%2040-28%2068l-136%20136q-28%2028-68%2028t-68-28l-294-294-294%20294q-28%2028-68%2028t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28%2068-28t68%2028l294%20294%20294-294q28-28%2068-28t68%2028l136%20136q28%2028%2028%2068t-28%2068l-294%20294%20294%20294q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) no-repeat 9px 6px / 14px 14px;
226 | }
227 |
228 | a.phpdebugbar-open-btn {
229 | 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%22folder-open%22%3E%3Cpath%20d%3D%22M1815%20952q0%2031-31%2066l-336%20396q-43%2051-120.5%2086.5t-143.5%2035.5h-1088q-34%200-60.5-13t-26.5-43q0-31%2031-66l336-396q43-51%20120.5-86.5t143.5-35.5h1088q34%200%2060.5%2013t26.5%2043zm-343-344v160h-832q-94%200-197%2047.5t-164%20119.5l-337%20396-5%206q0-4-.5-12.5t-.5-12.5v-960q0-92%2066-158t158-66h320q92%200%20158%2066t66%20158v32h544q92%200%20158%2066t66%20158z%22%2F%3E%3C%2Fsvg%3E) no-repeat 8px 6px / 14px 14px;
230 | }
231 |
232 | .phpdebugbar-indicator {
233 | position: relative;
234 | cursor: pointer;
235 | }
236 | .phpdebugbar-indicator span.phpdebugbar-text {
237 | margin-left: 5px;
238 | }
239 | .phpdebugbar-indicator span.phpdebugbar-tooltip {
240 | display: none;
241 | position: absolute;
242 | top: -30px;
243 | background: #efefef;
244 | opacity: .7;
245 | border: 1px solid #ccc;
246 | color: #555;
247 | font-size: 11px;
248 | padding: 2px 3px;
249 | z-index: 1000;
250 | text-align: center;
251 | width: 200%;
252 | right: 0;
253 | }
254 | .phpdebugbar-indicator:hover span.phpdebugbar-tooltip:not(.phpdebugbar-disabled) {
255 | display: block;
256 | }
257 |
258 | select.phpdebugbar-datasets-switcher {
259 | float: right;
260 | display: none;
261 | margin: 2px 0 0 7px;
262 | max-width: 200px;
263 | max-height: 23px;
264 | padding: 0;
265 | }
266 |
267 | /* -------------------------------------- */
268 |
269 | div.phpdebugbar-body {
270 | border-top: 1px solid #ccc;
271 | display: none;
272 | position: relative;
273 | height: 300px;
274 | }
275 |
276 | /* -------------------------------------- */
277 |
278 | div.phpdebugbar-panel {
279 | display: none;
280 | height: 100%;
281 | overflow: auto;
282 | width: 100%;
283 | }
284 | div.phpdebugbar-panel.phpdebugbar-active {
285 | display: block;
286 | }
287 |
288 | /* -------------------------------------- */
289 |
290 | div.phpdebugbar-mini-design a.phpdebugbar-tab {
291 | position: relative;
292 | border-right: 1px solid #ddd;
293 | }
294 | div.phpdebugbar-mini-design a.phpdebugbar-tab span.phpdebugbar-text {
295 | display: none;
296 | }
297 | div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
298 | display: block;
299 | position: absolute;
300 | top: -30px;
301 | background: #efefef;
302 | opacity: .7;
303 | border: 1px solid #ccc;
304 | color: #555;
305 | font-size: 11px;
306 | padding: 2px 3px;
307 | z-index: 1000;
308 | text-align: center;
309 | right: 0;
310 | }
311 | div.phpdebugbar-mini-design a.phpdebugbar-tab i {
312 | display:inline-block;
313 | }
314 |
--------------------------------------------------------------------------------
/assets/debugbar.js:
--------------------------------------------------------------------------------
1 | if (typeof(PhpDebugBar) == 'undefined') {
2 | // namespace
3 | var PhpDebugBar = {};
4 | PhpDebugBar.$ = jQuery;
5 | }
6 |
7 | (function($) {
8 |
9 | if (typeof(localStorage) == 'undefined') {
10 | // provide mock localStorage object for dumb browsers
11 | localStorage = {
12 | setItem: function(key, value) {},
13 | getItem: function(key) { return null; }
14 | };
15 | }
16 |
17 | if (typeof(PhpDebugBar.utils) == 'undefined') {
18 | PhpDebugBar.utils = {};
19 | }
20 |
21 | /**
22 | * Returns the value from an object property.
23 | * Using dots in the key, it is possible to retrieve nested property values
24 | *
25 | * @param {Object} dict
26 | * @param {String} key
27 | * @param {Object} default_value
28 | * @return {Object}
29 | */
30 | var getDictValue = PhpDebugBar.utils.getDictValue = function(dict, key, default_value) {
31 | var d = dict, parts = key.split('.');
32 | for (var i = 0; i < parts.length; i++) {
33 | if (!d[parts[i]]) {
34 | return default_value;
35 | }
36 | d = d[parts[i]];
37 | }
38 | return d;
39 | }
40 |
41 | /**
42 | * Counts the number of properties in an object
43 | *
44 | * @param {Object} obj
45 | * @return {Integer}
46 | */
47 | var getObjectSize = PhpDebugBar.utils.getObjectSize = function(obj) {
48 | if (Object.keys) {
49 | return Object.keys(obj).length;
50 | }
51 | var count = 0;
52 | for (var k in obj) {
53 | if (obj.hasOwnProperty(k)) {
54 | count++;
55 | }
56 | }
57 | return count;
58 | }
59 |
60 | /**
61 | * Returns a prefixed css class name
62 | *
63 | * @param {String} cls
64 | * @return {String}
65 | */
66 | PhpDebugBar.utils.csscls = function(cls, prefix) {
67 | if (cls.indexOf(' ') > -1) {
68 | var clss = cls.split(' '), out = [];
69 | for (var i = 0, c = clss.length; i < c; i++) {
70 | out.push(PhpDebugBar.utils.csscls(clss[i], prefix));
71 | }
72 | return out.join(' ');
73 | }
74 | if (cls.indexOf('.') === 0) {
75 | return '.' + prefix + cls.substr(1);
76 | }
77 | return prefix + cls;
78 | };
79 |
80 | /**
81 | * Creates a partial function of csscls where the second
82 | * argument is already defined
83 | *
84 | * @param {string} prefix
85 | * @return {Function}
86 | */
87 | PhpDebugBar.utils.makecsscls = function(prefix) {
88 | var f = function(cls) {
89 | return PhpDebugBar.utils.csscls(cls, prefix);
90 | };
91 | return f;
92 | }
93 |
94 | var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-');
95 |
96 |
97 | // ------------------------------------------------------------------
98 |
99 | /**
100 | * Base class for all elements with a visual component
101 | *
102 | * @param {Object} options
103 | * @constructor
104 | */
105 | var Widget = PhpDebugBar.Widget = function(options) {
106 | this._attributes = $.extend({}, this.defaults);
107 | this._boundAttributes = {};
108 | this.$el = $('<' + this.tagName + ' />');
109 | if (this.className) {
110 | this.$el.addClass(this.className);
111 | }
112 | this.initialize.apply(this, [options || {}]);
113 | this.render.apply(this);
114 | };
115 |
116 | $.extend(Widget.prototype, {
117 |
118 | tagName: 'div',
119 |
120 | className: null,
121 |
122 | defaults: {},
123 |
124 | /**
125 | * Called after the constructor
126 | *
127 | * @param {Object} options
128 | */
129 | initialize: function(options) {
130 | this.set(options);
131 | },
132 |
133 | /**
134 | * Called after the constructor to render the element
135 | */
136 | render: function() {},
137 |
138 | /**
139 | * Sets the value of an attribute
140 | *
141 | * @param {String} attr Can also be an object to set multiple attributes at once
142 | * @param {Object} value
143 | */
144 | set: function(attr, value) {
145 | if (typeof(attr) != 'string') {
146 | for (var k in attr) {
147 | this.set(k, attr[k]);
148 | }
149 | return;
150 | }
151 |
152 | this._attributes[attr] = value;
153 | if (typeof(this._boundAttributes[attr]) !== 'undefined') {
154 | for (var i = 0, c = this._boundAttributes[attr].length; i < c; i++) {
155 | this._boundAttributes[attr][i].apply(this, [value]);
156 | }
157 | }
158 | },
159 |
160 | /**
161 | * Checks if an attribute exists and is not null
162 | *
163 | * @param {String} attr
164 | * @return {[type]} [description]
165 | */
166 | has: function(attr) {
167 | return typeof(this._attributes[attr]) !== 'undefined' && this._attributes[attr] !== null;
168 | },
169 |
170 | /**
171 | * Returns the value of an attribute
172 | *
173 | * @param {String} attr
174 | * @return {Object}
175 | */
176 | get: function(attr) {
177 | return this._attributes[attr];
178 | },
179 |
180 | /**
181 | * Registers a callback function that will be called whenever the value of the attribute changes
182 | *
183 | * If cb is a jQuery element, text() will be used to fill the element
184 | *
185 | * @param {String} attr
186 | * @param {Function} cb
187 | */
188 | bindAttr: function(attr, cb) {
189 | if ($.isArray(attr)) {
190 | for (var i = 0, c = attr.length; i < c; i++) {
191 | this.bindAttr(attr[i], cb);
192 | }
193 | return;
194 | }
195 |
196 | if (typeof(this._boundAttributes[attr]) == 'undefined') {
197 | this._boundAttributes[attr] = [];
198 | }
199 | if (typeof(cb) == 'object') {
200 | var el = cb;
201 | cb = function(value) { el.text(value || ''); };
202 | }
203 | this._boundAttributes[attr].push(cb);
204 | if (this.has(attr)) {
205 | cb.apply(this, [this._attributes[attr]]);
206 | }
207 | }
208 |
209 | });
210 |
211 |
212 | /**
213 | * Creates a subclass
214 | *
215 | * Code from Backbone.js
216 | *
217 | * @param {Array} props Prototype properties
218 | * @return {Function}
219 | */
220 | Widget.extend = function(props) {
221 | var parent = this;
222 |
223 | var child = function() { return parent.apply(this, arguments); };
224 | $.extend(child, parent);
225 |
226 | var Surrogate = function() { this.constructor = child; };
227 | Surrogate.prototype = parent.prototype;
228 | child.prototype = new Surrogate;
229 | $.extend(child.prototype, props);
230 |
231 | child.__super__ = parent.prototype;
232 |
233 | return child;
234 | };
235 |
236 | // ------------------------------------------------------------------
237 |
238 | /**
239 | * Tab
240 | *
241 | * A tab is composed of a tab label which is always visible and
242 | * a tab panel which is visible only when the tab is active.
243 | *
244 | * The panel must contain a widget. A widget is an object which has
245 | * an element property containing something appendable to a jQuery object.
246 | *
247 | * Options:
248 | * - title
249 | * - badge
250 | * - widget
251 | * - data: forward data to widget data
252 | */
253 | var Tab = Widget.extend({
254 |
255 | className: csscls('panel'),
256 |
257 | render: function() {
258 | this.$tab = $(' ').addClass(csscls('tab'));
259 |
260 | this.$icon = $(' ').appendTo(this.$tab);
261 | this.bindAttr('icon', function(icon) {
262 | if (icon) {
263 | this.$icon.attr('class', 'phpdebugbar-fa phpdebugbar-fa-' + icon);
264 | } else {
265 | this.$icon.attr('class', '');
266 | }
267 | });
268 |
269 | this.bindAttr('title', $(' ').addClass(csscls('text')).appendTo(this.$tab));
270 |
271 | this.$badge = $(' ').addClass(csscls('badge')).appendTo(this.$tab);
272 | this.bindAttr('badge', function(value) {
273 | if (value !== null) {
274 | this.$badge.text(value);
275 | this.$badge.addClass(csscls('visible'));
276 | } else {
277 | this.$badge.removeClass(csscls('visible'));
278 | }
279 | });
280 |
281 | this.bindAttr('widget', function(widget) {
282 | this.$el.empty().append(widget.$el);
283 | });
284 |
285 | this.bindAttr('data', function(data) {
286 | if (this.has('widget')) {
287 | this.get('widget').set('data', data);
288 | }
289 | })
290 | }
291 |
292 | });
293 |
294 | // ------------------------------------------------------------------
295 |
296 | /**
297 | * Indicator
298 | *
299 | * An indicator is a text and an icon to display single value information
300 | * right inside the always visible part of the debug bar
301 | *
302 | * Options:
303 | * - icon
304 | * - title
305 | * - tooltip
306 | * - data: alias of title
307 | */
308 | var Indicator = Widget.extend({
309 |
310 | tagName: 'span',
311 |
312 | className: csscls('indicator'),
313 |
314 | render: function() {
315 | this.$icon = $(' ').appendTo(this.$el);
316 | this.bindAttr('icon', function(icon) {
317 | if (icon) {
318 | this.$icon.attr('class', 'phpdebugbar-fa phpdebugbar-fa-' + icon);
319 | } else {
320 | this.$icon.attr('class', '');
321 | }
322 | });
323 |
324 | this.bindAttr(['title', 'data'], $(' ').addClass(csscls('text')).appendTo(this.$el));
325 |
326 | this.$tooltip = $(' ').addClass(csscls('tooltip disabled')).appendTo(this.$el);
327 | this.bindAttr('tooltip', function(tooltip) {
328 | if (tooltip) {
329 | this.$tooltip.text(tooltip).removeClass(csscls('disabled'));
330 | } else {
331 | this.$tooltip.addClass(csscls('disabled'));
332 | }
333 | });
334 | }
335 |
336 | });
337 |
338 | // ------------------------------------------------------------------
339 |
340 | /**
341 | * Dataset title formater
342 | *
343 | * Formats the title of a dataset for the select box
344 | */
345 | var DatasetTitleFormater = PhpDebugBar.DatasetTitleFormater = function(debugbar) {
346 | this.debugbar = debugbar;
347 | };
348 |
349 | $.extend(DatasetTitleFormater.prototype, {
350 |
351 | /**
352 | * Formats the title of a dataset
353 | *
354 | * @this {DatasetTitleFormater}
355 | * @param {String} id
356 | * @param {Object} data
357 | * @param {String} suffix
358 | * @return {String}
359 | */
360 | format: function(id, data, suffix) {
361 | if (suffix) {
362 | suffix = ' ' + suffix;
363 | } else {
364 | suffix = '';
365 | }
366 |
367 | var nb = getObjectSize(this.debugbar.datasets) + 1;
368 |
369 | if (typeof(data['__meta']) === 'undefined') {
370 | return "#" + nb + suffix;
371 | }
372 |
373 | var uri = data['__meta']['uri'], filename;
374 | if (uri.length && uri.charAt(uri.length - 1) === '/') {
375 | // URI ends in a trailing /: get the portion before then to avoid returning an empty string
376 | filename = uri.substr(0, uri.length - 1); // strip trailing '/'
377 | filename = filename.substr(filename.lastIndexOf('/') + 1); // get last path segment
378 | filename += '/'; // add the trailing '/' back
379 | } else {
380 | filename = uri.substr(uri.lastIndexOf('/') + 1);
381 | }
382 |
383 | // truncate the filename in the label, if it's too long
384 | var maxLength = 150;
385 | if (filename.length > maxLength) {
386 | filename = filename.substr(0, maxLength) + '...';
387 | }
388 |
389 | var label = "#" + nb + " " + filename + suffix + ' (' + data['__meta']['datetime'].split(' ')[1] + ')';
390 | return label;
391 | }
392 |
393 | });
394 |
395 | // ------------------------------------------------------------------
396 |
397 |
398 | /**
399 | * DebugBar
400 | *
401 | * Creates a bar that appends itself to the body of your page
402 | * and sticks to the bottom.
403 | *
404 | * The bar can be customized by adding tabs and indicators.
405 | * A data map is used to fill those controls with data provided
406 | * from datasets.
407 | */
408 | var DebugBar = PhpDebugBar.DebugBar = Widget.extend({
409 |
410 | className: "phpdebugbar " + csscls('minimized'),
411 |
412 | options: {
413 | bodyMarginBottom: true,
414 | bodyMarginBottomHeight: 0
415 | },
416 |
417 | initialize: function() {
418 | this.controls = {};
419 | this.dataMap = {};
420 | this.datasets = {};
421 | this.firstTabName = null;
422 | this.activePanelName = null;
423 | this.datesetTitleFormater = new DatasetTitleFormater(this);
424 | this.options.bodyMarginBottomHeight = parseInt($('body').css('margin-bottom'));
425 | this.registerResizeHandler();
426 | },
427 |
428 | /**
429 | * Register resize event, for resize debugbar with reponsive css.
430 | *
431 | * @this {DebugBar}
432 | */
433 | registerResizeHandler: function() {
434 | if (typeof this.resize.bind == 'undefined') return;
435 |
436 | var f = this.resize.bind(this);
437 | this.respCSSSize = 0;
438 | $(window).resize(f);
439 | setTimeout(f, 20);
440 | },
441 |
442 | /**
443 | * Resizes the debugbar to fit the current browser window
444 | */
445 | resize: function() {
446 | var contentSize = this.respCSSSize;
447 | if (this.respCSSSize == 0) {
448 | this.$header.find("> div > *:visible").each(function () {
449 | contentSize += $(this).outerWidth();
450 | });
451 | }
452 |
453 | var currentSize = this.$header.width();
454 | var cssClass = "phpdebugbar-mini-design";
455 | var bool = this.$header.hasClass(cssClass);
456 |
457 | if (currentSize <= contentSize && !bool) {
458 | this.respCSSSize = contentSize;
459 | this.$header.addClass(cssClass);
460 | } else if (contentSize < currentSize && bool) {
461 | this.respCSSSize = 0;
462 | this.$header.removeClass(cssClass);
463 | }
464 |
465 | // Reset height to ensure bar is still visible
466 | this.setHeight(this.$body.height());
467 | },
468 |
469 | /**
470 | * Initialiazes the UI
471 | *
472 | * @this {DebugBar}
473 | */
474 | render: function() {
475 | var self = this;
476 | this.$el.appendTo('body');
477 | this.$dragCapture = $('
4 |
5 | */
6 |
7 | div.phpdebugbar .hljs {
8 | display: block; padding: 0.5em;
9 | color: #333;
10 | background: #f8f8f8
11 | }
12 |
13 | div.phpdebugbar .hljs-comment,
14 | div.phpdebugbar .hljs-template_comment,
15 | div.phpdebugbar .diff .hljs-header,
16 | div.phpdebugbar .hljs-javadoc {
17 | color: #998;
18 | font-style: italic
19 | }
20 |
21 | div.phpdebugbar .hljs-keyword,
22 | div.phpdebugbar .css .rule .hljs-keyword,
23 | div.phpdebugbar .hljs-winutils,
24 | div.phpdebugbar .javascript .hljs-title,
25 | div.phpdebugbar .nginx .hljs-title,
26 | div.phpdebugbar .hljs-subst,
27 | div.phpdebugbar .hljs-request,
28 | div.phpdebugbar .hljs-status {
29 | color: #333;
30 | font-weight: bold
31 | }
32 |
33 | div.phpdebugbar .hljs-number,
34 | div.phpdebugbar .hljs-hexcolor,
35 | div.phpdebugbar .ruby .hljs-constant {
36 | color: #099;
37 | }
38 |
39 | div.phpdebugbar .hljs-string,
40 | div.phpdebugbar .hljs-tag .hljs-value,
41 | div.phpdebugbar .hljs-phpdoc,
42 | div.phpdebugbar .tex .hljs-formula {
43 | color: #d14
44 | }
45 |
46 | div.phpdebugbar .hljs-title,
47 | div.phpdebugbar .hljs-id,
48 | div.phpdebugbar .coffeescript .hljs-params,
49 | div.phpdebugbar .scss .hljs-preprocessor {
50 | color: #900;
51 | font-weight: bold
52 | }
53 |
54 | div.phpdebugbar .javascript .hljs-title,
55 | div.phpdebugbar .lisp .hljs-title,
56 | div.phpdebugbar .clojure .hljs-title,
57 | div.phpdebugbar .hljs-subst {
58 | font-weight: normal
59 | }
60 |
61 | div.phpdebugbar .hljs-class .hljs-title,
62 | div.phpdebugbar .haskell .hljs-type,
63 | div.phpdebugbar .vhdl .hljs-literal,
64 | div.phpdebugbar .tex .hljs-command {
65 | color: #458;
66 | font-weight: bold
67 | }
68 |
69 | div.phpdebugbar .hljs-tag,
70 | div.phpdebugbar .hljs-tag .hljs-title,
71 | div.phpdebugbar .hljs-rules .hljs-property,
72 | div.phpdebugbar .django .hljs-tag .hljs-keyword {
73 | color: #000080;
74 | font-weight: normal
75 | }
76 |
77 | div.phpdebugbar .hljs-attribute,
78 | div.phpdebugbar .hljs-variable,
79 | div.phpdebugbar .lisp .hljs-body {
80 | color: #008080
81 | }
82 |
83 | div.phpdebugbar .hljs-regexp {
84 | color: #009926
85 | }
86 |
87 | div.phpdebugbar .hljs-symbol,
88 | div.phpdebugbar .ruby .hljs-symbol .hljs-string,
89 | div.phpdebugbar .lisp .hljs-keyword,
90 | div.phpdebugbar .tex .hljs-special,
91 | div.phpdebugbar .hljs-prompt {
92 | color: #990073
93 | }
94 |
95 | div.phpdebugbar .hljs-built_in,
96 | div.phpdebugbar .lisp .hljs-title,
97 | div.phpdebugbar .clojure .hljs-built_in {
98 | color: #0086b3
99 | }
100 |
101 | div.phpdebugbar .hljs-preprocessor,
102 | div.phpdebugbar .hljs-pragma,
103 | div.phpdebugbar .hljs-pi,
104 | div.phpdebugbar .hljs-doctype,
105 | div.phpdebugbar .hljs-shebang,
106 | div.phpdebugbar .hljs-cdata {
107 | color: #999;
108 | font-weight: bold
109 | }
110 |
111 | div.phpdebugbar .hljs-deletion {
112 | background: #fdd
113 | }
114 |
115 | div.phpdebugbar .hljs-addition {
116 | background: #dfd
117 | }
118 |
119 | div.phpdebugbar .diff .hljs-change {
120 | background: #0086b3
121 | }
122 |
123 | div.phpdebugbar .hljs-chunk {
124 | color: #aaa
125 | }
126 |
--------------------------------------------------------------------------------
/assets/widgets.css:
--------------------------------------------------------------------------------
1 | pre.phpdebugbar-widgets-code-block {
2 | white-space: pre;
3 | word-wrap: normal;
4 | overflow: hidden;
5 | }
6 | pre.phpdebugbar-widgets-code-block code {
7 | display: block;
8 | overflow-x: auto;
9 | overflow-y: hidden;
10 | }
11 | pre.phpdebugbar-widgets-code-block code.phpdebugbar-widgets-numbered-code {
12 | padding: 5px;
13 | }
14 | pre.phpdebugbar-widgets-code-block code span.phpdebugbar-widgets-highlighted-line {
15 | background: #800000;
16 | color: #fff;
17 | display: inline-block;
18 | min-width: 100%;
19 | }
20 | pre.phpdebugbar-widgets-code-block code span.phpdebugbar-widgets-highlighted-line span {
21 | background: none !important;
22 | color: inherit !important;
23 | }
24 | pre.phpdebugbar-widgets-code-block ul {
25 | float: left;
26 | padding: 5px;
27 | background: #cacaca;
28 | border-right: 1px solid #aaa;
29 | text-align: right;
30 | }
31 |
32 | /* -------------------------------------- */
33 |
34 | ul.phpdebugbar-widgets-list {
35 | margin: 0;
36 | padding: 0;
37 | list-style: none;
38 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
39 | }
40 | ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
41 | padding: 3px 6px;
42 | border-bottom: 1px solid #eee;
43 | position: relative;
44 | overflow: hidden;
45 | }
46 | ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:hover {
47 | background: #fafafa;
48 | }
49 |
50 | /* -------------------------------------- */
51 |
52 | div.phpdebugbar-widgets-messages {
53 | position: relative;
54 | height: 100%;
55 | }
56 | div.phpdebugbar-widgets-messages ul.phpdebugbar-widgets-list {
57 | padding-bottom: 20px;
58 | }
59 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-warning:before {
60 | font-family: PhpDebugbarFontAwesome;
61 | content: "\f071";
62 | margin-right: 8px;
63 | font-size: 11px;
64 | color: #ecb03d;
65 | }
66 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error {
67 | color: red;
68 | }
69 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error:before {
70 | font-family: PhpDebugbarFontAwesome;
71 | content: "\f057";
72 | margin-right: 8px;
73 | font-size: 11px;
74 | color: red;
75 | }
76 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item pre.sf-dump {
77 | display: inline;
78 | }
79 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector,
80 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-label {
81 | float: right;
82 | font-size: 12px;
83 | padding: 2px 4px;
84 | color: #888;
85 | margin: 0 2px;
86 | text-decoration: none;
87 | text-shadow: none;
88 | background: none;
89 | font-weight: normal;
90 | }
91 | div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector {
92 | color: #555;
93 | font-style: italic;
94 | }
95 | div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar {
96 | position: fixed;
97 | bottom: 0;
98 | width: 100%;
99 | background: #fff;
100 | }
101 | div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input {
102 | border: 0;
103 | margin: 0;
104 | margin-left: 7px;
105 | width: 50%;
106 | box-shadow: none;
107 | }
108 | div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input:focus {
109 | outline: none;
110 | }
111 | div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter {
112 | float: right;
113 | font-size: 12px;
114 | padding: 2px 4px;
115 | background: #7cacd5;
116 | margin: 0 2px;
117 | border-radius: 4px;
118 | color: #fff;
119 | text-decoration: none;
120 | }
121 | div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
122 | background: #eee;
123 | color: #888;
124 | }
125 |
126 | /* -------------------------------------- */
127 |
128 | dl.phpdebugbar-widgets-kvlist {
129 | margin: 0;
130 | }
131 | dl.phpdebugbar-widgets-kvlist dt {
132 | float: left;
133 | width: 150px;
134 | padding: 5px;
135 | border-top: 1px solid #eee;
136 | font-weight: bold;
137 | clear: both;
138 | overflow: hidden;
139 | text-overflow: ellipsis;
140 | white-space: nowrap;
141 | }
142 | dl.phpdebugbar-widgets-kvlist dd {
143 | margin-left: 160px;
144 | padding: 5px;
145 | border-top: 1px solid #eee;
146 | cursor: pointer;
147 | min-height: 17px;
148 | }
149 |
150 | /* -------------------------------------- */
151 |
152 | dl.phpdebugbar-widgets-varlist,
153 | dl.phpdebugbar-widgets-htmlvarlist {
154 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
155 | }
156 | dl.phpdebugbar-widgets-htmlvarlist dd {
157 | cursor: initial;
158 | }
159 |
160 | /* -------------------------------------- */
161 |
162 | ul.phpdebugbar-widgets-timeline {
163 | margin: 0;
164 | padding: 0;
165 | list-style: none;
166 | }
167 | ul.phpdebugbar-widgets-timeline .phpdebugbar-widgets-measure {
168 | height: 20px;
169 | position: relative;
170 | border-bottom: 1px solid #eee;
171 | display: block;
172 | }
173 | ul.phpdebugbar-widgets-timeline li:hover {
174 | background: #fafafa;
175 | }
176 | ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
177 | ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
178 | position: absolute;
179 | font-size: 12px;
180 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
181 | color: #555;
182 | top: 4px;
183 | left: 5px;
184 | background: none;
185 | text-shadow: none;
186 | font-weight: normal;
187 | white-space: pre;
188 | }
189 | ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
190 | left: initial;
191 | right: 5px;
192 | }
193 | ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-value {
194 | display: block;
195 | position: absolute;
196 | height: 10px;
197 | background: #3db9ec;
198 | top: 5px;
199 | border-radius: 2px;
200 | min-width: 1px;
201 | }
202 | ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params {
203 | display: none;
204 | width: 70%;
205 | margin: 10px;
206 | border: 1px solid #ddd;
207 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
208 | border-collapse: collapse;
209 | }
210 | ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params td {
211 | border: 1px solid #ddd;
212 | padding: 0 5px;
213 | }
214 | ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params .phpdebugbar-widgets-name {
215 | width: 20%;
216 | font-weight: bold;
217 | }
218 |
219 | /* -------------------------------------- */
220 |
221 | div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item {
222 | cursor: pointer;
223 | }
224 | div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message {
225 | display: block;
226 | color: red;
227 | }
228 |
229 | div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
230 | display: block;
231 | font-style: italic;
232 | color: #555;
233 | }
234 |
235 | div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-type {
236 | display: block;
237 | position: absolute;
238 | right: 4px;
239 | top: 4px;
240 | font-weight: bold;
241 | }
242 |
243 | div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file {
244 | display: none;
245 | margin: 10px;
246 | padding: 5px;
247 | border: 1px solid #ddd;
248 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
249 | }
250 |
251 | div.phpdebugbar-widgets-exceptions a.phpdebugbar-widgets-editor-link:before {
252 | font-family: PhpDebugbarFontAwesome;
253 | margin-right: 4px;
254 | font-size: 12px;
255 | font-style: normal;
256 | }
257 |
258 | div.phpdebugbar-widgets-exceptions a.phpdebugbar-widgets-editor-link:before {
259 | content: "\f08e";
260 | margin-left: 4px;
261 | }
262 |
--------------------------------------------------------------------------------
/assets/widgets.js:
--------------------------------------------------------------------------------
1 | if (typeof(PhpDebugBar) == 'undefined') {
2 | // namespace
3 | var PhpDebugBar = {};
4 | PhpDebugBar.$ = jQuery;
5 | }
6 |
7 | (function($) {
8 |
9 | /**
10 | * @namespace
11 | */
12 | PhpDebugBar.Widgets = {};
13 |
14 | var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
15 |
16 | /**
17 | * Replaces spaces with and line breaks with
18 | *
19 | * @param {String} text
20 | * @return {String}
21 | */
22 | var htmlize = PhpDebugBar.Widgets.htmlize = function(text) {
23 | return text.replace(/\n/g, ' ').replace(/\s/g, " ")
24 | };
25 |
26 | /**
27 | * Returns a string representation of value, using JSON.stringify
28 | * if it's an object.
29 | *
30 | * @param {Object} value
31 | * @param {Boolean} prettify Uses htmlize() if true
32 | * @return {String}
33 | */
34 | var renderValue = PhpDebugBar.Widgets.renderValue = function(value, prettify) {
35 | if (typeof(value) !== 'string') {
36 | if (prettify) {
37 | return htmlize(JSON.stringify(value, undefined, 2));
38 | }
39 | return JSON.stringify(value);
40 | }
41 | return value;
42 | };
43 |
44 | /**
45 | * Highlights a block of code
46 | *
47 | * @param {String} code
48 | * @param {String} lang
49 | * @return {String}
50 | */
51 | var highlight = PhpDebugBar.Widgets.highlight = function(code, lang) {
52 | if (typeof(code) === 'string') {
53 | if (typeof(hljs) === 'undefined') {
54 | return htmlize(code);
55 | }
56 | if (lang) {
57 | return hljs.highlight(lang, code).value;
58 | }
59 | return hljs.highlightAuto(code).value;
60 | }
61 |
62 | if (typeof(hljs) === 'object') {
63 | code.each(function(i, e) { hljs.highlightBlock(e); });
64 | }
65 | return code;
66 | };
67 |
68 | /**
69 | * Creates a element with a block of code
70 | *
71 | * @param {String} code
72 | * @param {String} lang
73 | * @param {Number} [firstLineNumber] If provided, shows line numbers beginning with the given value.
74 | * @param {Number} [highlightedLine] If provided, the given line number will be highlighted.
75 | * @return {String}
76 | */
77 | var createCodeBlock = PhpDebugBar.Widgets.createCodeBlock = function(code, lang, firstLineNumber, highlightedLine) {
78 | var pre = $(' ').addClass(csscls('code-block'));
79 | // Add a newline to prevent element from vertically collapsing too far if the last
80 | // code line was empty: that creates problems with the horizontal scrollbar being
81 | // incorrectly positioned - most noticeable when line numbers are shown.
82 | var codeElement = $('
').text(code + '\n').appendTo(pre);
83 |
84 | // Add a span with a special class if we are supposed to highlight a line. highlight.js will
85 | // still correctly format code even with existing markup in it.
86 | if ($.isNumeric(highlightedLine)) {
87 | if ($.isNumeric(firstLineNumber)) {
88 | highlightedLine = highlightedLine - firstLineNumber + 1;
89 | }
90 | codeElement.html(function (index, html) {
91 | var currentLine = 1;
92 | return html.replace(/^.*$/gm, function(line) {
93 | if (currentLine++ == highlightedLine) {
94 | return '' + line + ' ';
95 | } else {
96 | return line;
97 | }
98 | });
99 | });
100 | }
101 |
102 | // Format the code
103 | if (lang) {
104 | pre.addClass("language-" + lang);
105 | }
106 | highlight(pre);
107 |
108 | // Show line numbers in a list
109 | if ($.isNumeric(firstLineNumber)) {
110 | var lineCount = code.split('\n').length;
111 | var $lineNumbers = $('').prependTo(pre);
112 | pre.children().addClass(csscls('numbered-code'));
113 | for (var i = firstLineNumber; i < firstLineNumber + lineCount; i++) {
114 | $(' ').text(i).appendTo($lineNumbers);
115 | }
116 | }
117 |
118 | return pre;
119 | };
120 |
121 | // ------------------------------------------------------------------
122 | // Generic widgets
123 | // ------------------------------------------------------------------
124 |
125 | /**
126 | * Displays array element in a list
127 | *
128 | * Options:
129 | * - data
130 | * - itemRenderer: a function used to render list items (optional)
131 | */
132 | var ListWidget = PhpDebugBar.Widgets.ListWidget = PhpDebugBar.Widget.extend({
133 |
134 | tagName: 'ul',
135 |
136 | className: csscls('list'),
137 |
138 | initialize: function(options) {
139 | if (!options['itemRenderer']) {
140 | options['itemRenderer'] = this.itemRenderer;
141 | }
142 | this.set(options);
143 | },
144 |
145 | render: function() {
146 | this.bindAttr(['itemRenderer', 'data'], function() {
147 | this.$el.empty();
148 | if (!this.has('data')) {
149 | return;
150 | }
151 |
152 | var data = this.get('data');
153 | for (var i = 0; i < data.length; i++) {
154 | var li = $(' ').addClass(csscls('list-item')).appendTo(this.$el);
155 | this.get('itemRenderer')(li, data[i]);
156 | }
157 | });
158 | },
159 |
160 | /**
161 | * Renders the content of a element
162 | *
163 | * @param {jQuery} li The element as a jQuery Object
164 | * @param {Object} value An item from the data array
165 | */
166 | itemRenderer: function(li, value) {
167 | li.html(renderValue(value));
168 | }
169 |
170 | });
171 |
172 | // ------------------------------------------------------------------
173 |
174 | /**
175 | * Displays object property/value paris in a list
176 | *
177 | * Options:
178 | * - data
179 | * - itemRenderer: a function used to render list items (optional)
180 | */
181 | var KVListWidget = PhpDebugBar.Widgets.KVListWidget = ListWidget.extend({
182 |
183 | tagName: 'dl',
184 |
185 | className: csscls('kvlist'),
186 |
187 | render: function() {
188 | this.bindAttr(['itemRenderer', 'data'], function() {
189 | this.$el.empty();
190 | if (!this.has('data')) {
191 | return;
192 | }
193 |
194 | var self = this;
195 | $.each(this.get('data'), function(key, value) {
196 | var dt = $(' ').addClass(csscls('key')).appendTo(self.$el);
197 | var dd = $(' ').addClass(csscls('value')).appendTo(self.$el);
198 | self.get('itemRenderer')(dt, dd, key, value);
199 | });
200 | });
201 | },
202 |
203 | /**
204 | * Renders the content of the and elements
205 | *
206 | * @param {jQuery} dt The element as a jQuery Object
207 | * @param {jQuery} dd The element as a jQuery Object
208 | * @param {String} key Property name
209 | * @param {Object} value Property value
210 | */
211 | itemRenderer: function(dt, dd, key, value) {
212 | dt.text(key);
213 | dd.html(htmlize(value));
214 | }
215 |
216 | });
217 |
218 | // ------------------------------------------------------------------
219 |
220 | /**
221 | * An extension of KVListWidget where the data represents a list
222 | * of variables
223 | *
224 | * Options:
225 | * - data
226 | */
227 | var VariableListWidget = PhpDebugBar.Widgets.VariableListWidget = KVListWidget.extend({
228 |
229 | className: csscls('kvlist varlist'),
230 |
231 | itemRenderer: function(dt, dd, key, value) {
232 | $(' ').attr('title', key).text(key).appendTo(dt);
233 |
234 | var v = value;
235 | if (v && v.length > 100) {
236 | v = v.substr(0, 100) + "...";
237 | }
238 | var prettyVal = null;
239 | dd.text(v).click(function() {
240 | if (dd.hasClass(csscls('pretty'))) {
241 | dd.text(v).removeClass(csscls('pretty'));
242 | } else {
243 | prettyVal = prettyVal || createCodeBlock(value);
244 | dd.addClass(csscls('pretty')).empty().append(prettyVal);
245 | }
246 | });
247 | }
248 |
249 | });
250 |
251 | // ------------------------------------------------------------------
252 |
253 | /**
254 | * An extension of KVListWidget where the data represents a list
255 | * of variables whose contents are HTML; this is useful for showing
256 | * variable output from VarDumper's HtmlDumper.
257 | *
258 | * Options:
259 | * - data
260 | */
261 | var HtmlVariableListWidget = PhpDebugBar.Widgets.HtmlVariableListWidget = KVListWidget.extend({
262 |
263 | className: csscls('kvlist htmlvarlist'),
264 |
265 | itemRenderer: function(dt, dd, key, value) {
266 | $(' ').attr('title', key).text(key).appendTo(dt);
267 | dd.html(value);
268 | }
269 |
270 | });
271 |
272 | // ------------------------------------------------------------------
273 |
274 | /**
275 | * Iframe widget
276 | *
277 | * Options:
278 | * - data
279 | */
280 | var IFrameWidget = PhpDebugBar.Widgets.IFrameWidget = PhpDebugBar.Widget.extend({
281 |
282 | tagName: 'iframe',
283 |
284 | className: csscls('iframe'),
285 |
286 | render: function() {
287 | this.$el.attr({
288 | seamless: "seamless",
289 | border: "0",
290 | width: "100%",
291 | height: "100%"
292 | });
293 | this.bindAttr('data', function(url) { this.$el.attr('src', url); });
294 | }
295 |
296 | });
297 |
298 |
299 | // ------------------------------------------------------------------
300 | // Collector specific widgets
301 | // ------------------------------------------------------------------
302 |
303 | /**
304 | * Widget for the MessagesCollector
305 | *
306 | * Uses ListWidget under the hood
307 | *
308 | * Options:
309 | * - data
310 | */
311 | var MessagesWidget = PhpDebugBar.Widgets.MessagesWidget = PhpDebugBar.Widget.extend({
312 |
313 | className: csscls('messages'),
314 |
315 | render: function() {
316 | var self = this;
317 |
318 | this.$list = new ListWidget({ itemRenderer: function(li, value) {
319 | if (value.message_html) {
320 | var val = $(' ').addClass(csscls('value')).html(value.message_html).appendTo(li);
321 | } else {
322 | var m = value.message;
323 | if (m.length > 100) {
324 | m = m.substr(0, 100) + "...";
325 | }
326 |
327 | var val = $(' ').addClass(csscls('value')).text(m).appendTo(li);
328 | if (!value.is_string || value.message.length > 100) {
329 | var prettyVal = value.message;
330 | if (!value.is_string) {
331 | prettyVal = null;
332 | }
333 | li.css('cursor', 'pointer').click(function () {
334 | if (val.hasClass(csscls('pretty'))) {
335 | val.text(m).removeClass(csscls('pretty'));
336 | } else {
337 | prettyVal = prettyVal || createCodeBlock(value.message, 'php');
338 | val.addClass(csscls('pretty')).empty().append(prettyVal);
339 | }
340 | });
341 | }
342 | }
343 |
344 | if (value.collector) {
345 | $(' ').addClass(csscls('collector')).text(value.collector).prependTo(li);
346 | }
347 | if (value.label) {
348 | val.addClass(csscls(value.label));
349 | $(' ').addClass(csscls('label')).text(value.label).prependTo(li);
350 | }
351 | }});
352 |
353 | this.$list.$el.appendTo(this.$el);
354 | this.$toolbar = $('
').addClass(csscls('toolbar')).appendTo(this.$el);
355 |
356 | $(' ')
357 | .on('change', function() { self.set('search', this.value); })
358 | .appendTo(this.$toolbar);
359 |
360 | this.bindAttr('data', function(data) {
361 | this.set({ exclude: [], search: '' });
362 | this.$toolbar.find(csscls('.filter')).remove();
363 |
364 | var filters = [], self = this;
365 | for (var i = 0; i < data.length; i++) {
366 | if (!data[i].label || $.inArray(data[i].label, filters) > -1) {
367 | continue;
368 | }
369 | filters.push(data[i].label);
370 | $(' ')
371 | .addClass(csscls('filter'))
372 | .text(data[i].label)
373 | .attr('rel', data[i].label)
374 | .on('click', function() { self.onFilterClick(this); })
375 | .appendTo(this.$toolbar);
376 | }
377 | });
378 |
379 | this.bindAttr(['exclude', 'search'], function() {
380 | var data = this.get('data'),
381 | exclude = this.get('exclude'),
382 | search = this.get('search'),
383 | caseless = false,
384 | fdata = [];
385 |
386 | if (search && search === search.toLowerCase()) {
387 | caseless = true;
388 | }
389 |
390 | for (var i = 0; i < data.length; i++) {
391 | var message = caseless ? data[i].message.toLowerCase() : data[i].message;
392 |
393 | if ((!data[i].label || $.inArray(data[i].label, exclude) === -1) && (!search || message.indexOf(search) > -1)) {
394 | fdata.push(data[i]);
395 | }
396 | }
397 |
398 | this.$list.set('data', fdata);
399 | });
400 | },
401 |
402 | onFilterClick: function(el) {
403 | $(el).toggleClass(csscls('excluded'));
404 |
405 | var excludedLabels = [];
406 | this.$toolbar.find(csscls('.filter') + csscls('.excluded')).each(function() {
407 | excludedLabels.push(this.rel);
408 | });
409 |
410 | this.set('exclude', excludedLabels);
411 | }
412 |
413 | });
414 |
415 | // ------------------------------------------------------------------
416 |
417 | /**
418 | * Widget for the TimeDataCollector
419 | *
420 | * Options:
421 | * - data
422 | */
423 | var TimelineWidget = PhpDebugBar.Widgets.TimelineWidget = PhpDebugBar.Widget.extend({
424 |
425 | tagName: 'ul',
426 |
427 | className: csscls('timeline'),
428 |
429 | render: function() {
430 | this.bindAttr('data', function(data) {
431 |
432 | // ported from php DataFormatter
433 | var formatDuration = function(seconds) {
434 | if (seconds < 0.001)
435 | return (seconds * 1000000).toFixed() + 'μs';
436 | else if (seconds < 1)
437 | return (seconds * 1000).toFixed(2) + 'ms';
438 | return (seconds).toFixed(2) + 's';
439 | };
440 |
441 | this.$el.empty();
442 | if (data.measures) {
443 | var aggregate = {};
444 |
445 | for (var i = 0; i < data.measures.length; i++) {
446 | var measure = data.measures[i];
447 |
448 | if(!aggregate[measure.label])
449 | aggregate[measure.label] = { count: 0, duration: 0 };
450 |
451 | aggregate[measure.label]['count'] += 1;
452 | aggregate[measure.label]['duration'] += measure.duration;
453 |
454 | var m = $('
').addClass(csscls('measure')),
455 | li = $(' '),
456 | left = (measure.relative_start * 100 / data.duration).toFixed(2),
457 | width = Math.min((measure.duration * 100 / data.duration).toFixed(2), 100 - left);
458 |
459 | m.append($(' ').addClass(csscls('value')).css({
460 | left: left + "%",
461 | width: width + "%"
462 | }));
463 | m.append($(' ').addClass(csscls('label')).text(measure.label + " (" + measure.duration_str + ")"));
464 |
465 | if (measure.collector) {
466 | $(' ').addClass(csscls('collector')).text(measure.collector).appendTo(m);
467 | }
468 |
469 | m.appendTo(li);
470 | this.$el.append(li);
471 |
472 | if (measure.params && !$.isEmptyObject(measure.params)) {
473 | var table = $('').addClass(csscls('params')).appendTo(li);
474 | for (var key in measure.params) {
475 | if (typeof measure.params[key] !== 'function') {
476 | table.append('' + key + ' ' + measure.params[key] + '
');
478 | }
479 | }
480 | li.css('cursor', 'pointer').click(function() {
481 | var table = $(this).find('table');
482 | if (table.is(':visible')) {
483 | table.hide();
484 | } else {
485 | table.show();
486 | }
487 | });
488 | }
489 | }
490 |
491 | // convert to array and sort by duration
492 | aggregate = $.map(aggregate, function(data, label) {
493 | return {
494 | label: label,
495 | data: data
496 | }
497 | }).sort(function(a, b) {
498 | return b.data.duration - a.data.duration
499 | });
500 |
501 | // build table and add
502 | var aggregateTable = $('').addClass(csscls('params'));
503 | $.each(aggregate, function(i, aggregate) {
504 | width = Math.min((aggregate.data.duration * 100 / data.duration).toFixed(2), 100);
505 |
506 | aggregateTable.append('' + aggregate.data.count + ' x ' + aggregate.label + ' (' + width + '%) ' +
507 | '' +
508 | ' ' +
509 | '' + formatDuration(aggregate.data.duration) + ' ' +
510 | '
');
511 | });
512 |
513 | this.$el.append(' ').find('li:last').append(aggregateTable);
514 | }
515 | });
516 | }
517 |
518 | });
519 |
520 | // ------------------------------------------------------------------
521 |
522 | /**
523 | * Widget for the displaying exceptions
524 | *
525 | * Options:
526 | * - data
527 | */
528 | var ExceptionsWidget = PhpDebugBar.Widgets.ExceptionsWidget = PhpDebugBar.Widget.extend({
529 |
530 | className: csscls('exceptions'),
531 |
532 | render: function() {
533 | this.$list = new ListWidget({ itemRenderer: function(li, e) {
534 | $(' ').addClass(csscls('message')).text(e.message).appendTo(li);
535 | if (e.file) {
536 | var header = $(' ').addClass(csscls('filename')).text(e.file + "#" + e.line);
537 | if (e.xdebug_link) {
538 | if (e.xdebug_link.ajax) {
539 | $(' ').on('click', function () {
540 | $.ajax(e.xdebug_link.url);
541 | }).addClass(csscls('editor-link')).appendTo(header);
542 | } else {
543 | $(' ').addClass(csscls('editor-link')).appendTo(header);
544 | }
545 | }
546 | header.appendTo(li);
547 | }
548 | if (e.type) {
549 | $(' ').addClass(csscls('type')).text(e.type).appendTo(li);
550 | }
551 | if (e.surrounding_lines) {
552 | var pre = createCodeBlock(e.surrounding_lines.join(""), 'php').addClass(csscls('file')).appendTo(li);
553 | if (!e.stack_trace_html) {
554 | // This click event makes the var-dumper hard to use.
555 | li.click(function () {
556 | if (pre.is(':visible')) {
557 | pre.hide();
558 | } else {
559 | pre.show();
560 | }
561 | });
562 | }
563 | }
564 | if (e.stack_trace_html) {
565 | var $trace = $(' ').addClass(csscls('filename')).html(e.stack_trace_html);
566 | $trace.appendTo(li);
567 | } else if (e.stack_trace) {
568 | e.stack_trace.split("\n").forEach(function (trace) {
569 | var $traceLine = $('
');
570 | $(' ').addClass(csscls('filename')).text(trace).appendTo($traceLine);
571 | $traceLine.appendTo(li);
572 | });
573 | }
574 | }});
575 | this.$list.$el.appendTo(this.$el);
576 |
577 | this.bindAttr('data', function(data) {
578 | this.$list.set('data', data);
579 | if (data.length == 1) {
580 | this.$list.$el.children().first().find(csscls('.file')).show();
581 | }
582 | });
583 |
584 | }
585 |
586 | });
587 |
588 |
589 | })(PhpDebugBar.$);
590 |
--------------------------------------------------------------------------------
/assets/widgets/mails/widget.css:
--------------------------------------------------------------------------------
1 |
2 | div.phpdebugbar-widgets-mails span.phpdebugbar-widgets-subject {
3 | display: block;
4 | }
5 |
6 | div.phpdebugbar-widgets-mails li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-headers {
7 | display: none;
8 | margin: 10px;
9 | padding: 5px;
10 | border: 1px solid #ddd;
11 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
12 | }
13 |
--------------------------------------------------------------------------------
/assets/widgets/mails/widget.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 |
3 | var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
4 |
5 | /**
6 | * Widget for the displaying mails data
7 | *
8 | * Options:
9 | * - data
10 | */
11 | var MailsWidget = PhpDebugBar.Widgets.MailsWidget = PhpDebugBar.Widget.extend({
12 |
13 | className: csscls('mails'),
14 |
15 | render: function() {
16 | this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, mail) {
17 | $(' ').addClass(csscls('subject')).text(mail.subject).appendTo(li);
18 | $(' ').addClass(csscls('to')).text(mail.to).appendTo(li);
19 | if (mail.headers) {
20 | var headers = $(' ').addClass(csscls('headers')).appendTo(li);
21 | $('
').text(mail.headers).appendTo(headers);
22 | li.click(function() {
23 | if (headers.is(':visible')) {
24 | headers.hide();
25 | } else {
26 | headers.show();
27 | }
28 | });
29 | }
30 | }});
31 | this.$list.$el.appendTo(this.$el);
32 |
33 | this.bindAttr('data', function(data) {
34 | this.$list.set('data', data);
35 | });
36 | }
37 |
38 | });
39 |
40 | })(PhpDebugBar.$);
41 |
--------------------------------------------------------------------------------
/assets/widgets/sqlqueries/widget.css:
--------------------------------------------------------------------------------
1 | div.phpdebugbar-widgets-sqlqueries .phpdebugbar-widgets-status {
2 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
3 | padding: 6px 6px;
4 | border-bottom: 1px solid #ddd;
5 | font-weight: bold;
6 | color: #555;
7 | background: #fafafa;
8 | }
9 |
10 | div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-error {
11 | color: red;
12 | }
13 |
14 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database,
15 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration,
16 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory,
17 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count,
18 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard,
19 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id {
20 | float: right;
21 | margin-left: 8px;
22 | color: #888;
23 | }
24 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-database,
25 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-duration,
26 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-memory,
27 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-row-count,
28 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-copy-clipboard,
29 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-stmt-id {
30 | color: #555;
31 | }
32 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database:before,
33 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before,
34 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before,
35 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before,
36 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before,
37 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before {
38 | font-family: PhpDebugbarFontAwesome;
39 | margin-right: 4px;
40 | font-size: 12px;
41 | }
42 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database:before {
43 | content: "\f1c0";
44 | }
45 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before {
46 | content: "\f017";
47 | }
48 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before {
49 | content: "\f085";
50 | }
51 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before {
52 | content: "\f0ce";
53 | }
54 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before {
55 | content: "\f08d";
56 | }
57 | div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before {
58 | content: "\f0c5";
59 | }
60 | div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params {
61 | display: none;
62 | width: 70%;
63 | margin: 10px;
64 | border: 1px solid #ddd;
65 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
66 | border-collapse: collapse;
67 | }
68 | div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td {
69 | border: 1px solid #ddd;
70 | text-align: center;
71 | }
72 | div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params .phpdebugbar-widgets-name {
73 | width: 20%;
74 | font-weight: bold;
75 | }
76 |
77 | div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-error {
78 | display: block;
79 | font-weight: bold;
80 | }
81 |
82 | code.phpdebugbar-widgets-sql {
83 | white-space: pre-wrap;
84 | overflow-wrap: break-word;
85 | word-wrap: break-word;
86 | }
87 |
88 | div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate {
89 | background-color: #edeff0;
90 | }
91 |
92 | div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate:hover {
93 | background-color: #ffc;
94 | }
95 |
96 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar {
97 | display:none;
98 | position: fixed;
99 | bottom: 0;
100 | width: 100%;
101 | background: #fff;
102 | z-index: 1;
103 | }
104 |
105 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter {
106 | float: right;
107 | font-size: 12px;
108 | padding: 2px 4px;
109 | background: #7cacd5;
110 | margin: 0 2px;
111 | border-radius: 4px;
112 | color: #fff;
113 | text-decoration: none;
114 | }
115 | div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
116 | background: #eee;
117 | color: #888;
118 | }
119 |
--------------------------------------------------------------------------------
/assets/widgets/sqlqueries/widget.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 |
3 | var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
4 |
5 | /**
6 | * Widget for the displaying sql queries
7 | *
8 | * Options:
9 | * - data
10 | */
11 | var SQLQueriesWidget = PhpDebugBar.Widgets.SQLQueriesWidget = PhpDebugBar.Widget.extend({
12 |
13 | className: csscls('sqlqueries'),
14 |
15 | onFilterClick: function(el) {
16 | $(el).toggleClass(csscls('excluded'));
17 |
18 | var excludedLabels = [];
19 | this.$toolbar.find(csscls('.filter') + csscls('.excluded')).each(function() {
20 | excludedLabels.push(this.rel);
21 | });
22 |
23 | this.$list.$el.find("li[connection=" + $(el).attr("rel") + "]").toggle();
24 |
25 | this.set('exclude', excludedLabels);
26 | },
27 | onCopyToClipboard: function (el) {
28 | var code = $(el).parent('li').find('code').get(0);
29 | var copy = function () {
30 | try {
31 | document.execCommand('copy');
32 | alert('Query copied to the clipboard');
33 | } catch (err) {
34 | console.log('Oops, unable to copy');
35 | }
36 | };
37 | var select = function (node) {
38 | if (document.selection) {
39 | var range = document.body.createTextRange();
40 | range.moveToElementText(node);
41 | range.select();
42 | } else if (window.getSelection) {
43 | var range = document.createRange();
44 | range.selectNodeContents(node);
45 | window.getSelection().removeAllRanges();
46 | window.getSelection().addRange(range);
47 | }
48 | copy();
49 | window.getSelection().removeAllRanges();
50 | };
51 | select(code);
52 | },
53 | render: function() {
54 | this.$status = $('
').addClass(csscls('status')).appendTo(this.$el);
55 |
56 | this.$toolbar = $('
').addClass(csscls('toolbar')).appendTo(this.$el);
57 |
58 | var filters = [], self = this;
59 |
60 | this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, stmt) {
61 | $('
').addClass(csscls('sql')).html(PhpDebugBar.Widgets.highlight(stmt.sql, 'sql')).appendTo(li);
62 | if (stmt.duration_str) {
63 | $(' ').addClass(csscls('duration')).text(stmt.duration_str).appendTo(li);
64 | }
65 | if (stmt.memory_str) {
66 | $(' ').addClass(csscls('memory')).text(stmt.memory_str).appendTo(li);
67 | }
68 | if (typeof(stmt.row_count) != 'undefined') {
69 | $(' ').addClass(csscls('row-count')).text(stmt.row_count).appendTo(li);
70 | }
71 | if (typeof(stmt.stmt_id) != 'undefined' && stmt.stmt_id) {
72 | $(' ').addClass(csscls('stmt-id')).text(stmt.stmt_id).appendTo(li);
73 | }
74 | if (stmt.connection) {
75 | $(' ').addClass(csscls('database')).text(stmt.connection).appendTo(li);
76 | li.attr("connection",stmt.connection);
77 | if ( $.inArray(stmt.connection, filters) == -1 ) {
78 | filters.push(stmt.connection);
79 | $(' ')
80 | .addClass(csscls('filter'))
81 | .text(stmt.connection)
82 | .attr('rel', stmt.connection)
83 | .on('click', function() { self.onFilterClick(this); })
84 | .appendTo(self.$toolbar);
85 | if (filters.length>1) {
86 | self.$toolbar.show();
87 | self.$list.$el.css("margin-bottom","20px");
88 | }
89 | }
90 | }
91 | if (typeof(stmt.is_success) != 'undefined' && !stmt.is_success) {
92 | li.addClass(csscls('error'));
93 | li.append($(' ').addClass(csscls('error')).text("[" + stmt.error_code + "] " + stmt.error_message));
94 | }
95 | $(' ')
96 | .addClass(csscls('copy-clipboard'))
97 | .css('cursor', 'pointer')
98 | .on('click', function (event) {
99 | self.onCopyToClipboard(this);
100 | event.stopPropagation();
101 | })
102 | .appendTo(li);
103 | if (stmt.params && !$.isEmptyObject(stmt.params)) {
104 | var table = $('').addClass(csscls('params')).appendTo(li);
105 | for (var key in stmt.params) {
106 | if (typeof stmt.params[key] !== 'function') {
107 | table.append('' + key + ' ' + stmt.params[key] + ' ');
109 | }
110 | }
111 | li.css('cursor', 'pointer').click(function() {
112 | if (table.is(':visible')) {
113 | table.hide();
114 | } else {
115 | table.show();
116 | }
117 | });
118 | }
119 | }});
120 | this.$list.$el.appendTo(this.$el);
121 |
122 | this.bindAttr('data', function(data) {
123 | // the PDO collector maybe is empty
124 | if (data.length <= 0) {
125 | return false;
126 | }
127 | this.$list.set('data', data.statements);
128 | this.$status.empty();
129 |
130 | // Search for duplicate statements.
131 | for (var sql = {}, unique = 0, duplicate = 0, i = 0; i < data.statements.length; i++) {
132 | var stmt = data.statements[i].sql;
133 | if (data.statements[i].params && !$.isEmptyObject(data.statements[i].params)) {
134 | stmt += ' {' + $.param(data.statements[i].params, false) + '}';
135 | }
136 | sql[stmt] = sql[stmt] || { keys: [] };
137 | sql[stmt].keys.push(i);
138 | }
139 | // Add classes to all duplicate SQL statements.
140 | for (var stmt in sql) {
141 | if (sql[stmt].keys.length > 1) {
142 | duplicate += sql[stmt].keys.length;
143 | for (var i = 0; i < sql[stmt].keys.length; i++) {
144 | this.$list.$el.find('.' + csscls('list-item')).eq(sql[stmt].keys[i])
145 | .addClass(csscls('sql-duplicate'));
146 | }
147 | } else {
148 | unique++;
149 | }
150 | }
151 |
152 | var t = $(' ').text(data.nb_statements + " statements were executed").appendTo(this.$status);
153 | if (data.nb_failed_statements) {
154 | t.append(", " + data.nb_failed_statements + " of which failed");
155 | }
156 | if (duplicate) {
157 | t.append(", " + duplicate + " of which were duplicates");
158 | t.append(", " + unique + " unique");
159 | }
160 | if (data.accumulated_duration_str) {
161 | this.$status.append($(' ').addClass(csscls('duration')).text(data.accumulated_duration_str));
162 | }
163 | if (data.memory_usage_str) {
164 | this.$status.append($(' ').addClass(csscls('memory')).text(data.memory_usage_str));
165 | }
166 | });
167 | }
168 |
169 | });
170 |
171 | })(PhpDebugBar.$);
172 |
--------------------------------------------------------------------------------
/assets/widgets/templates/widget.css:
--------------------------------------------------------------------------------
1 |
2 | div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status {
3 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
4 | padding: 6px 6px;
5 | border-bottom: 1px solid #ddd;
6 | font-weight: bold;
7 | color: #555;
8 | background: #fafafa;
9 | }
10 |
11 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time,
12 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory,
13 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count,
14 | div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link,
15 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type {
16 | float: right;
17 | margin-left: 8px;
18 | color: #888;
19 | }
20 | div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-render-time,
21 | div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-memory,
22 | div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-param-count,
23 | div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status a.phpdebugbar-widgets-editor-link,
24 | div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-type {
25 | color: #555;
26 | }
27 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time:before,
28 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory:before,
29 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count:before,
30 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type:before,
31 | div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:before,
32 | div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:before
33 | {
34 | font-family: PhpDebugbarFontAwesome;
35 | margin-right: 4px;
36 | font-size: 12px;
37 | }
38 | div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:hover
39 | {
40 | color: #ffffff;
41 | }
42 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time:before {
43 | content: "\f017";
44 | }
45 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory:before {
46 | content: "\f085";
47 | }
48 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count:before {
49 | content: "\f0ce";
50 | }
51 | div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type:before {
52 | content: "\f121";
53 | }
54 | div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:before {
55 | content: "\f08e";
56 | margin-left: 4px;
57 | }
58 | div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params {
59 | display: none;
60 | width: 70%;
61 | margin: 10px;
62 | border: 1px solid #ddd;
63 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
64 | border-collapse: collapse;
65 | }
66 | div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params td {
67 | border: 1px solid #ddd;
68 | padding: 0 5px;
69 | }
70 | div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params .phpdebugbar-widgets-name {
71 | width: 20%;
72 | font-weight: bold;
73 | }
74 |
--------------------------------------------------------------------------------
/assets/widgets/templates/widget.js:
--------------------------------------------------------------------------------
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.TemplatesWidget = PhpDebugBar.Widget.extend({
12 |
13 | className: csscls('templates'),
14 |
15 | render: function() {
16 | this.$status = $('
').addClass(csscls('status')).appendTo(this.$el);
17 |
18 | this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, tpl) {
19 | $(' ').addClass(csscls('name')).text(tpl.name).appendTo(li);
20 |
21 | if (typeof tpl.xdebug_link !== 'undefined' && tpl.xdebug_link !== null) {
22 | if (tpl.xdebug_link.ajax) {
23 | $(' ').on('click', function () {
24 | $.ajax(tpl.xdebug_link.url);
25 | }).addClass(csscls('editor-link')).appendTo(li);
26 | } else {
27 | $(' ').addClass(csscls('editor-link')).appendTo(li);
28 | }
29 | }
30 | if (tpl.render_time_str) {
31 | $(' ').addClass(csscls('render-time')).text(tpl.render_time_str).appendTo(li);
32 | }
33 | if (tpl.memory_str) {
34 | $(' ').addClass(csscls('memory')).text(tpl.memory_str).appendTo(li);
35 | }
36 | if (typeof(tpl.param_count) != 'undefined') {
37 | $(' ').addClass(csscls('param-count')).text(tpl.param_count).appendTo(li);
38 | }
39 | if (typeof(tpl.type) != 'undefined' && tpl.type) {
40 | $(' ').addClass(csscls('type')).text(tpl.type).appendTo(li);
41 | }
42 | if (typeof(tpl.editorLink) != 'undefined' && tpl.editorLink) {
43 | $(' ').addClass(csscls('editor-link')).text('file').appendTo(li);
44 | }
45 | if (tpl.params && !$.isEmptyObject(tpl.params)) {
46 | var table = $('').addClass(csscls('params')).appendTo(li);
47 | for (var key in tpl.params) {
48 | if (typeof tpl.params[key] !== 'function') {
49 | table.append('' + key + ' ' + tpl.params[key] + '
');
51 | }
52 | }
53 | li.css('cursor', 'pointer').click(function() {
54 | if (table.is(':visible')) {
55 | table.hide();
56 | } else {
57 | table.show();
58 | }
59 | });
60 | }
61 | }});
62 | this.$list.$el.appendTo(this.$el);
63 | this.$callgraph = $('
').addClass(csscls('callgraph')).appendTo(this.$el);
64 |
65 | this.bindAttr('data', function(data) {
66 | this.$list.set('data', data.templates);
67 | this.$status.empty();
68 | this.$callgraph.empty();
69 |
70 | var sentence = data.sentence || "templates were rendered";
71 | $(' ').text(data.nb_templates + " " + sentence).appendTo(this.$status);
72 |
73 | if (data.accumulated_render_time_str) {
74 | this.$status.append($(' ').addClass(csscls('render-time')).text(data.accumulated_render_time_str));
75 | }
76 | if (data.memory_usage_str) {
77 | this.$status.append($(' ').addClass(csscls('memory')).text(data.memory_usage_str));
78 | }
79 | if (data.nb_blocks > 0) {
80 | $('
').text(data.nb_blocks + " blocks were rendered").appendTo(this.$status);
81 | }
82 | if (data.nb_macros > 0) {
83 | $('
').text(data.nb_macros + " macros were rendered").appendTo(this.$status);
84 | }
85 | if (typeof data.callgraph !== 'undefined') {
86 | this.$callgraph.html(data.callgraph);
87 | }
88 | });
89 | }
90 |
91 | });
92 |
93 | })(PhpDebugBar.$);
94 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "treast/kirby-debugbar",
3 | "description": "PHP Debug Bar for KirbyCMS",
4 | "type": "kirby-plugin",
5 | "version": "1.4.1",
6 | "keywords": [
7 | "kirby",
8 | "kirbycms",
9 | "debugbar",
10 | "profiler",
11 | "debug"
12 | ],
13 | "homepage": "https://github.com/Treast/kirby-debugbar",
14 | "support": {
15 | "issues": "https://github.com/Treast/kirby-debugbar/issues",
16 | "source": "https://github.com/Treast/kirby-debugbar"
17 | },
18 | "license": "MIT",
19 | "autoload": {
20 | "psr-4": {
21 | "Treast\\KirbyDebugbar\\": "src/"
22 | }
23 | },
24 | "authors": [
25 | {
26 | "name": "Vincent Riva",
27 | "email": "vincent.riva@outlook.fr",
28 | "homepage": "https://www.vincentriva.fr",
29 | "role": "Developer"
30 | }
31 | ],
32 | "require": {
33 | "php-debugbar/php-debugbar": "^2.1",
34 | "getkirby/composer-installer": "^1.2"
35 | },
36 | "config": {
37 | "optimize-autoloader": true,
38 | "allow-plugins": {
39 | "getkirby/composer-installer": true
40 | }
41 | },
42 | "extra": {
43 | "installer-name": "debugbar"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "4abcc618b56bd0897759a393245f3f95",
8 | "packages": [
9 | {
10 | "name": "getkirby/composer-installer",
11 | "version": "1.2.1",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/getkirby/composer-installer.git",
15 | "reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/getkirby/composer-installer/zipball/c98ece30bfba45be7ce457e1102d1b169d922f3d",
20 | "reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "composer-plugin-api": "^1.0 || ^2.0"
25 | },
26 | "require-dev": {
27 | "composer/composer": "^1.8 || ^2.0"
28 | },
29 | "type": "composer-plugin",
30 | "extra": {
31 | "class": "Kirby\\ComposerInstaller\\Plugin"
32 | },
33 | "autoload": {
34 | "psr-4": {
35 | "Kirby\\": "src/"
36 | }
37 | },
38 | "notification-url": "https://packagist.org/downloads/",
39 | "license": [
40 | "MIT"
41 | ],
42 | "description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins",
43 | "homepage": "https://getkirby.com",
44 | "support": {
45 | "issues": "https://github.com/getkirby/composer-installer/issues",
46 | "source": "https://github.com/getkirby/composer-installer/tree/1.2.1"
47 | },
48 | "funding": [
49 | {
50 | "url": "https://getkirby.com/buy",
51 | "type": "custom"
52 | }
53 | ],
54 | "time": "2020-12-28T12:54:39+00:00"
55 | },
56 | {
57 | "name": "php-debugbar/php-debugbar",
58 | "version": "v2.1.6",
59 | "source": {
60 | "type": "git",
61 | "url": "https://github.com/php-debugbar/php-debugbar.git",
62 | "reference": "16fa68da5617220594aa5e33fa9de415f94784a0"
63 | },
64 | "dist": {
65 | "type": "zip",
66 | "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/16fa68da5617220594aa5e33fa9de415f94784a0",
67 | "reference": "16fa68da5617220594aa5e33fa9de415f94784a0",
68 | "shasum": ""
69 | },
70 | "require": {
71 | "php": "^8",
72 | "psr/log": "^1|^2|^3",
73 | "symfony/var-dumper": "^4|^5|^6|^7"
74 | },
75 | "require-dev": {
76 | "dbrekelmans/bdi": "^1",
77 | "phpunit/phpunit": "^8|^9",
78 | "symfony/panther": "^1|^2.1",
79 | "twig/twig": "^1.38|^2.7|^3.0"
80 | },
81 | "suggest": {
82 | "kriswallsmith/assetic": "The best way to manage assets",
83 | "monolog/monolog": "Log using Monolog",
84 | "predis/predis": "Redis storage"
85 | },
86 | "type": "library",
87 | "extra": {
88 | "branch-alias": {
89 | "dev-master": "2.0-dev"
90 | }
91 | },
92 | "autoload": {
93 | "psr-4": {
94 | "DebugBar\\": "src/DebugBar/"
95 | }
96 | },
97 | "notification-url": "https://packagist.org/downloads/",
98 | "license": [
99 | "MIT"
100 | ],
101 | "authors": [
102 | {
103 | "name": "Maxime Bouroumeau-Fuseau",
104 | "email": "maxime.bouroumeau@gmail.com",
105 | "homepage": "http://maximebf.com"
106 | },
107 | {
108 | "name": "Barry vd. Heuvel",
109 | "email": "barryvdh@gmail.com"
110 | }
111 | ],
112 | "description": "Debug bar in the browser for php application",
113 | "homepage": "https://github.com/php-debugbar/php-debugbar",
114 | "keywords": [
115 | "debug",
116 | "debug bar",
117 | "debugbar",
118 | "dev"
119 | ],
120 | "support": {
121 | "issues": "https://github.com/php-debugbar/php-debugbar/issues",
122 | "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.1.6"
123 | },
124 | "time": "2025-02-21T17:47:03+00:00"
125 | },
126 | {
127 | "name": "psr/log",
128 | "version": "3.0.0",
129 | "source": {
130 | "type": "git",
131 | "url": "https://github.com/php-fig/log.git",
132 | "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
133 | },
134 | "dist": {
135 | "type": "zip",
136 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
137 | "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
138 | "shasum": ""
139 | },
140 | "require": {
141 | "php": ">=8.0.0"
142 | },
143 | "type": "library",
144 | "extra": {
145 | "branch-alias": {
146 | "dev-master": "3.x-dev"
147 | }
148 | },
149 | "autoload": {
150 | "psr-4": {
151 | "Psr\\Log\\": "src"
152 | }
153 | },
154 | "notification-url": "https://packagist.org/downloads/",
155 | "license": [
156 | "MIT"
157 | ],
158 | "authors": [
159 | {
160 | "name": "PHP-FIG",
161 | "homepage": "https://www.php-fig.org/"
162 | }
163 | ],
164 | "description": "Common interface for logging libraries",
165 | "homepage": "https://github.com/php-fig/log",
166 | "keywords": [
167 | "log",
168 | "psr",
169 | "psr-3"
170 | ],
171 | "support": {
172 | "source": "https://github.com/php-fig/log/tree/3.0.0"
173 | },
174 | "time": "2021-07-14T16:46:02+00:00"
175 | },
176 | {
177 | "name": "symfony/polyfill-mbstring",
178 | "version": "v1.27.0",
179 | "source": {
180 | "type": "git",
181 | "url": "https://github.com/symfony/polyfill-mbstring.git",
182 | "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
183 | },
184 | "dist": {
185 | "type": "zip",
186 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
187 | "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
188 | "shasum": ""
189 | },
190 | "require": {
191 | "php": ">=7.1"
192 | },
193 | "provide": {
194 | "ext-mbstring": "*"
195 | },
196 | "suggest": {
197 | "ext-mbstring": "For best performance"
198 | },
199 | "type": "library",
200 | "extra": {
201 | "branch-alias": {
202 | "dev-main": "1.27-dev"
203 | },
204 | "thanks": {
205 | "name": "symfony/polyfill",
206 | "url": "https://github.com/symfony/polyfill"
207 | }
208 | },
209 | "autoload": {
210 | "files": [
211 | "bootstrap.php"
212 | ],
213 | "psr-4": {
214 | "Symfony\\Polyfill\\Mbstring\\": ""
215 | }
216 | },
217 | "notification-url": "https://packagist.org/downloads/",
218 | "license": [
219 | "MIT"
220 | ],
221 | "authors": [
222 | {
223 | "name": "Nicolas Grekas",
224 | "email": "p@tchwork.com"
225 | },
226 | {
227 | "name": "Symfony Community",
228 | "homepage": "https://symfony.com/contributors"
229 | }
230 | ],
231 | "description": "Symfony polyfill for the Mbstring extension",
232 | "homepage": "https://symfony.com",
233 | "keywords": [
234 | "compatibility",
235 | "mbstring",
236 | "polyfill",
237 | "portable",
238 | "shim"
239 | ],
240 | "support": {
241 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
242 | },
243 | "funding": [
244 | {
245 | "url": "https://symfony.com/sponsor",
246 | "type": "custom"
247 | },
248 | {
249 | "url": "https://github.com/fabpot",
250 | "type": "github"
251 | },
252 | {
253 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
254 | "type": "tidelift"
255 | }
256 | ],
257 | "time": "2022-11-03T14:55:06+00:00"
258 | },
259 | {
260 | "name": "symfony/var-dumper",
261 | "version": "v6.2.10",
262 | "source": {
263 | "type": "git",
264 | "url": "https://github.com/symfony/var-dumper.git",
265 | "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab"
266 | },
267 | "dist": {
268 | "type": "zip",
269 | "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41a750a23412ca76fdbbf5096943b4134272c1ab",
270 | "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab",
271 | "shasum": ""
272 | },
273 | "require": {
274 | "php": ">=8.1",
275 | "symfony/polyfill-mbstring": "~1.0"
276 | },
277 | "conflict": {
278 | "phpunit/phpunit": "<5.4.3",
279 | "symfony/console": "<5.4"
280 | },
281 | "require-dev": {
282 | "ext-iconv": "*",
283 | "symfony/console": "^5.4|^6.0",
284 | "symfony/process": "^5.4|^6.0",
285 | "symfony/uid": "^5.4|^6.0",
286 | "twig/twig": "^2.13|^3.0.4"
287 | },
288 | "suggest": {
289 | "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
290 | "ext-intl": "To show region name in time zone dump",
291 | "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
292 | },
293 | "bin": [
294 | "Resources/bin/var-dump-server"
295 | ],
296 | "type": "library",
297 | "autoload": {
298 | "files": [
299 | "Resources/functions/dump.php"
300 | ],
301 | "psr-4": {
302 | "Symfony\\Component\\VarDumper\\": ""
303 | },
304 | "exclude-from-classmap": [
305 | "/Tests/"
306 | ]
307 | },
308 | "notification-url": "https://packagist.org/downloads/",
309 | "license": [
310 | "MIT"
311 | ],
312 | "authors": [
313 | {
314 | "name": "Nicolas Grekas",
315 | "email": "p@tchwork.com"
316 | },
317 | {
318 | "name": "Symfony Community",
319 | "homepage": "https://symfony.com/contributors"
320 | }
321 | ],
322 | "description": "Provides mechanisms for walking through any arbitrary PHP variable",
323 | "homepage": "https://symfony.com",
324 | "keywords": [
325 | "debug",
326 | "dump"
327 | ],
328 | "support": {
329 | "source": "https://github.com/symfony/var-dumper/tree/v6.2.10"
330 | },
331 | "funding": [
332 | {
333 | "url": "https://symfony.com/sponsor",
334 | "type": "custom"
335 | },
336 | {
337 | "url": "https://github.com/fabpot",
338 | "type": "github"
339 | },
340 | {
341 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
342 | "type": "tidelift"
343 | }
344 | ],
345 | "time": "2023-04-18T13:46:08+00:00"
346 | }
347 | ],
348 | "packages-dev": [],
349 | "aliases": [],
350 | "minimum-stability": "stable",
351 | "stability-flags": [],
352 | "prefer-stable": false,
353 | "prefer-lowest": false,
354 | "platform": [],
355 | "platform-dev": [],
356 | "plugin-api-version": "2.6.0"
357 | }
358 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | [
9 | 'force' => false,
10 | 'tabs' => [
11 | 'logs' => true,
12 | 'config' => true,
13 | 'events' => true,
14 | 'files' => true,
15 | 'variables' => true,
16 | 'request' => true,
17 | 'exceptions' => true
18 | ]
19 | ],
20 | 'hooks' => [
21 | 'system.loadPlugins:after' => function () {
22 | \Treast\KirbyDebugbar\Debugbar::init(kirby());
23 | },
24 | 'page.render:before' => function (string $contentType, array $data, \Kirby\Cms\Page $page) {
25 | \Treast\KirbyDebugbar\Debugbar::logPage($page);
26 | return $data;
27 | },
28 | '*:after' => function (\Kirby\Cms\Event $event) {
29 | \Treast\KirbyDebugbar\Debugbar::logEvent($event);
30 | },
31 | 'system.exception' => function (Throwable $exception) {
32 | if ($exception instanceof Exception) \Treast\KirbyDebugbar\Debugbar::logException($exception);
33 | },
34 | ],
35 | 'snippets' => [
36 | 'debugbar' => __DIR__ . '/snippets/debugbar.php'
37 | ],
38 | 'siteMethods' => [
39 | 'logger' => function () {
40 | return \Treast\KirbyDebugbar\Debugbar::getLogger();
41 | },
42 | 'log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)
43 | ],
44 | 'pageMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
45 | 'pagesMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
46 | 'fieldMethods' => ['log' => fn ($field) => \Treast\KirbyDebugbar\Debugbar::logUtils($field)],
47 | 'fileMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
48 | 'filesMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
49 | 'userMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
50 | 'usersMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
51 | 'collectionMethods' => ['log' => fn () => \Treast\KirbyDebugbar\Debugbar::logUtils($this)],
52 | ]);
53 |
--------------------------------------------------------------------------------
/snippets/debugbar.php:
--------------------------------------------------------------------------------
1 | renderHead();
9 | echo css('/media/plugins/treast/debugbar/index.css');
10 | echo Debugbar::getRenderer()->render();
11 | }
12 |
--------------------------------------------------------------------------------
/src/DataCollector/EventCollector.php:
--------------------------------------------------------------------------------
1 | name = $name;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/DataCollector/FileCollector.php:
--------------------------------------------------------------------------------
1 | name = $name;
16 | }
17 |
18 | public function addFile(string $type, string $file)
19 | {
20 | if (!isset($this->files[$type])) $this->files[$type] = [];
21 | $this->files[$type][] = $file;
22 | }
23 |
24 | public function addFiles(string $type, array $files)
25 | {
26 | foreach ($files as $file) {
27 | if (is_string($file)) $this->addFile($type, $file);
28 | }
29 | }
30 |
31 | public function getName()
32 | {
33 | return $this->name;
34 | }
35 |
36 | public function collect()
37 | {
38 | $data = [];
39 |
40 | foreach ($this->files as $type => $file) {
41 | $data[$type] = $this->getDataFormatter()->formatVar($file);
42 | }
43 |
44 | return $data;
45 | }
46 |
47 | public function getWidgets()
48 | {
49 | $name = $this->getName();
50 |
51 | return array(
52 | "$name" => array(
53 | "icon" => "tags",
54 | "widget" => "PhpDebugBar.Widgets.VariableListWidget",
55 | "map" => "$name",
56 | "default" => "{}"
57 | )
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/DataCollector/VariableCollector.php:
--------------------------------------------------------------------------------
1 | name = $name;
16 | }
17 |
18 | public function getName()
19 | {
20 | return $this->name;
21 | }
22 |
23 | public function setContent(array $content)
24 | {
25 | $this->content = $content;
26 | }
27 |
28 | public function collect()
29 | {
30 | $data = [];
31 |
32 | foreach ($this->content as $key => $var) {
33 | $data[$key] = $this->getDataFormatter()->formatVar($var);
34 | }
35 |
36 | return $data;
37 | }
38 |
39 | public function getWidgets()
40 | {
41 | $name = $this->getName();
42 |
43 | return array(
44 | "$name" => array(
45 | "icon" => "tags",
46 | "widget" => "PhpDebugBar.Widgets.VariableListWidget",
47 | "map" => "$name",
48 | "default" => "{}"
49 | )
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Debugbar.php:
--------------------------------------------------------------------------------
1 | root('config') . '/config.php');
31 |
32 | self::$logger = new Logger();
33 |
34 | self::$debugbar = new DebugBarDebugBar();
35 | if (option('treast.debugbar.tabs.logs')) self::$debugbar->addCollector(new MessagesCollector('logs'));
36 | if (option('treast.debugbar.tabs.config')) self::$debugbar->addCollector(new ConfigCollector($config));
37 | if (option('treast.debugbar.tabs.events')) self::$debugbar->addCollector(new EventCollector());
38 | if (option('treast.debugbar.tabs.files')) self::$debugbar->addCollector(new FileCollector());
39 | if (option('treast.debugbar.tabs.variables')) self::$debugbar->addCollector(new VariableCollector());
40 | if (option('treast.debugbar.tabs.exceptions')) self::$debugbar->addCollector(new ExceptionsCollector());
41 | if (option('treast.debugbar.tabs.request')) self::$debugbar->addCollector(new RequestDataCollector());
42 | self::$debugbar->addCollector(new PhpInfoCollector());
43 | self::$debugbar->addCollector(new MemoryCollector());
44 | }
45 |
46 | public static function getLogger()
47 | {
48 | return self::$logger;
49 | }
50 |
51 | public static function getRenderer($baseUrl = null)
52 | {
53 | return self::$debugbar->getJavascriptRenderer($baseUrl);
54 | }
55 |
56 | public static function logUtils(mixed $data)
57 | {
58 | self::log($data, 'debug');
59 | return $data;
60 | }
61 |
62 | public static function log($data, $label = 'info', $channel = 'logs')
63 | {
64 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.logs')) self::$debugbar->getCollector($channel)->addMessage($data, $label);
65 | }
66 |
67 | public static function logEvent(Event $event)
68 | {
69 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.events')) self::log($event, 'info', 'events');
70 | }
71 |
72 | public static function logException(\Exception $e)
73 | {
74 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.exceptions')) self::$debugbar->getCollector('exceptions')->addException($e);
75 | }
76 |
77 | private static function logFiles(string $type, array $files)
78 | {
79 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.files')) self::$debugbar->getCollector('files')->addFiles($type, $files);
80 | }
81 |
82 | private static function logVariables($content)
83 | {
84 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.variables')) self::$debugbar->getCollector('variables')->setContent($content);
85 | }
86 |
87 | public static function logPage(Page $page)
88 | {
89 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.files')) {
90 | self::logFiles('Content', $page->content()->toArray());
91 | self::logFiles('Files', array_column($page->files()->toArray(), 'url'));
92 | self::logFiles('Children', array_column(array_map(function ($child) {
93 | return $child['content'];
94 | }, $page->children()->toArray()), 'title'));
95 | }
96 |
97 | if ((option('debug') || option('treast.debugbar.force')) && option('treast.debugbar.tabs.variables')) self::logVariables($page->content()->data());
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Logger.php:
--------------------------------------------------------------------------------
1 |