Commit ffcd14c3 authored by Andreas Fernandez's avatar Andreas Fernandez
Browse files

[!!!][TASK] Drop DebugConsole

The DebugConsole comes from ExtJS times and was triggered when e.g. a
request failed to give a developer its response, including the
stacktrace. Nowadays, browsers offer a console allowing to investigate
requests. Also, PHP debuggers (e.g. xdebug) are commonly known and used,
which makes the DebugConsole obsolete.

Resolves: #98069
Releases: main
Change-Id: I8adcb6594d6434b4d0e0314219087b3230324c9f
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75348

Tested-by: Nikita Hovratov's avatarNikita Hovratov <nikita.h@live.de>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Nikita Hovratov's avatarNikita Hovratov <nikita.h@live.de>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 11a6da25
......@@ -212,7 +212,6 @@ label {
// badge fallback
// todo use ".badge .rounded-pill .bg-{themeColor}" instead of only .badge
// todo only used in debug console?
[class="badge"] {
background-color: $gray-600;
border-radius: $rounded-pill;
......
......@@ -86,7 +86,6 @@
@import "typo3/main_backend_layout_wizard";
@import "typo3/main_form";
@import "typo3/main_new_content_element_wizard";
@import "typo3/debugconsole";
@import "typo3/wizard_localization";
@import "typo3/structure/module_web_list";
@import "typo3/structure/module_file_filelist";
......
$console-border-color: darken($gray-300, 15%);
#typo3-debug-console {
background-color: $gray-100;
width: 100%;
position: absolute;
bottom: 0;
z-index: 1000;
border: 1px solid $console-border-color;
.topbar {
background-color: $gray-300;
padding: $padding-base-vertical $padding-base-horizontal;
border-bottom: 1px solid $console-border-color;
.badge {
margin-left: $padding-base-vertical;
}
}
.messages {
background-color: $white;
padding: $padding-base-vertical $padding-base-horizontal;
font-family: $font-family-monospace;
height: 250px;
overflow: auto;
.table {
width: auto;
}
p {
margin: 0;
strong {
padding-right: $padding-small-horizontal;
}
}
}
}
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import $ from 'jquery';
import '@typo3/backend/element/icon-element';
/**
* Module: @typo3/backend/debug-console
* The debug console shown at the bottom of the backend
* @exports @typo3/backend/debug-console
*/
class DebugConsole {
private $consoleDom: any;
private settings: any = {
autoscroll: true,
};
/**
* Increment the counter of unread messages in the given tab
*
* @param {JQuery} $tab
*/
private static incrementInactiveTabCounter($tab: JQuery): void {
if (!$tab.hasClass('active')) {
const $badge = $tab.find('.badge');
let value = parseInt($badge.text(), 10);
if (isNaN(value)) {
value = 0;
}
$badge.text(++value);
}
}
constructor() {
$((): void => {
this.createDom();
});
}
/**
* Add the debug message to the console
*
* @param {String} message
* @param {String} header
* @param {String} [group=Debug]
*/
public add(message: string, header: string, group: string): void {
this.attachToViewport();
const $line = $('<p />').html(message);
if (typeof header !== 'undefined' && header.length > 0) {
$line.prepend($('<strong />').text(header));
}
if (typeof group === 'undefined' || group.length === 0) {
group = 'Debug';
}
const tabIdentifier = 'debugtab-' + group.toLowerCase().replace(/\W+/g, '-');
const $debugTabs = this.$consoleDom.find('.t3js-debuggroups');
const $tabContent = this.$consoleDom.find('.t3js-debugcontent');
let $tab = this.$consoleDom.find('.t3js-debuggroups li[data-identifier=' + tabIdentifier + ']');
// check if group tab exists
if ($tab.length === 0) {
// create new tab
$tab =
$('<li />', {role: 'presentation', class: 'nav-item', 'data-identifier': tabIdentifier}).append(
$('<a />', {
'aria-controls': tabIdentifier,
'data-bs-toggle': 'tab',
class: 'nav-link',
href: '#' + tabIdentifier,
role: 'tab',
}).text(group + ' ').append(
$('<span />', {'class': 'badge'}),
),
).on('shown.bs.tab', (e: Event) => {
$(e.currentTarget).find('.badge').text('');
});
$debugTabs.append($tab);
$tabContent.append(
$('<div />', {role: 'tabpanel', 'class': 'tab-pane', id: tabIdentifier}).append(
$('<div />', {'class': 't3js-messages messages'}),
),
);
}
// activate the first tab if no one is active
if ($debugTabs.find('.active').length === 0) {
$debugTabs.find('a:first').tab('show');
}
DebugConsole.incrementInactiveTabCounter($tab);
this.incrementUnreadMessagesIfCollapsed();
const $messageBox = $('#' + tabIdentifier + ' .t3js-messages');
const isMessageBoxActive = $messageBox.parent().hasClass('active');
$messageBox.append($line);
if (this.settings.autoscroll && isMessageBoxActive) {
$messageBox.scrollTop($messageBox.prop('scrollHeight'));
}
}
private createDom(): void {
if (typeof this.$consoleDom !== 'undefined') {
return;
}
this.$consoleDom =
$('<div />', {id: 'typo3-debug-console'}).append(
$('<div />', {'class': 't3js-topbar topbar d-flex justify-content-between align-items-center'}).append(
$('<typo3-backend-icon />', {identifier: 'actions-terminal', size: 'small'}),
$('<span />', {'class': 'flex-fill'}).text('TYPO3 Debug Console').append(
$('<span />', {'class': 'badge'}),
),
$('<div />', {'class': 't3js-buttons btn-group'}),
),
$('<div />').append(
$('<div />', {role: 'tabpanel'}).append(
$('<ul />', {'class': 'nav nav-tabs t3js-debuggroups', role: 'tablist'}),
),
$('<div />', {'class': 'tab-content t3js-debugcontent'}),
),
);
this.addButton(
$('<button />', {
'class': 'btn btn-default btn-sm ' + (this.settings.autoscroll ? 'active' : ''),
title: TYPO3.lang['debuggerconsole.autoscroll'],
}).append($('<typo3-backend-icon />', {identifier: 'actions-magnet', size: 'small'})),
(): void => {
$(this).button('toggle');
this.settings.autoscroll = !this.settings.autoscroll;
},
).addButton(
$('<button />', {
'class': 'btn btn-default btn-sm',
title: TYPO3.lang['debuggerconsole.toggle.collapse'],
}).append($('<typo3-backend-icon />', {identifier: 'actions-chevron-down', size: 'small'})),
(e: Event): void => {
let $button = $(e.currentTarget);
let $icon = $button.find('typo3-backend-icon');
let $innerContainer = this.$consoleDom.find('.t3js-topbar').next();
$innerContainer.toggle();
if ($innerContainer.is(':visible')) {
$button.attr('title', TYPO3.lang['debuggerconsole.toggle.collapse']);
$icon.replaceWith($('<typo3-backend-icon />', {identifier: 'actions-chevron-down', size: 'small'}))
this.resetGlobalUnreadCounter();
} else {
$button.attr('title', TYPO3.lang['debuggerconsole.toggle.expand']);
$icon.replaceWith($('<typo3-backend-icon />', {identifier: 'actions-chevron-up', size: 'small'}))
}
},
).addButton(
$('<button />', {
'class': 'btn btn-default btn-sm',
title: TYPO3.lang['debuggerconsole.clear']}).append($('<typo3-backend-icon />', {identifier: 'actions-undo', size: 'small'})),
(): void => {
this.flush();
},
).addButton(
$('<button />', {
'class': 'btn btn-default btn-sm',
title: TYPO3.lang['debuggerconsole.close']}).append($('<typo3-backend-icon />', {identifier: 'actions-close', size: 'small'})),
(): void => {
this.destroy();
this.createDom();
},
);
}
/**
* Adds a button and it's callback to the console's toolbar
*
* @param {JQuery} $button
* @param callback
* @returns {DebugConsole}
*/
private addButton($button: JQuery, callback: any): this {
$button.on('click', callback);
this.$consoleDom.find('.t3js-buttons').append($button);
return this;
}
/**
* Attach the Debugger Console to the viewport
*/
private attachToViewport(): void {
const $viewport = $('.t3js-scaffold-content');
if ($viewport.has(this.$consoleDom).length === 0) {
$viewport.append(this.$consoleDom);
}
}
/**
* Increment the counter of unread messages in the tabbar
*/
private incrementUnreadMessagesIfCollapsed(): void {
const $topbar = this.$consoleDom.find('.t3js-topbar');
const $innerContainer = $topbar.next();
if ($innerContainer.is(':hidden')) {
const $badge = $topbar.find('.badge');
let value = parseInt($badge.text(), 10);
if (isNaN(value)) {
value = 0;
}
$badge.text(++value);
}
}
/**
* Reset global unread counter
*/
private resetGlobalUnreadCounter(): void {
this.$consoleDom.find('.t3js-topbar').find('.badge').text('');
}
/**
* Reset the console
*/
private flush(): void {
const $debugTabs = this.$consoleDom.find('.t3js-debuggroups');
const $tabContent = this.$consoleDom.find('.t3js-debugcontent');
$debugTabs.children().remove();
$tabContent.children().remove();
}
/**
* Destroy everything of the console
*/
private destroy(): void {
this.$consoleDom.remove();
this.$consoleDom = undefined;
}
}
const debugConsole = new DebugConsole();
// expose as global object
TYPO3.DebugConsole = debugConsole;
export default debugConsole;
......@@ -6,7 +6,6 @@
*/
declare namespace TYPO3 {
export let Backend: any;
export let DebugConsole: any;
export let ExtensionManager: any;
export let FormEngine: any;
export let Icons: any;
......
......@@ -18,11 +18,10 @@
7: '@typo3/backend/modal.js',
8: '@typo3/backend/info-window.js',
9: '@typo3/backend/viewport/resizable-navigation.js',
10: '@typo3/backend/debug-console.js',
11: '@typo3/backend/context-menu.js',
12: '@typo3/backend/global-event-handler.js',
13: '@typo3/backend/action-dispatcher.js',
14: '@typo3/backend/element/immediate-action-element.js'
10: '@typo3/backend/context-menu.js',
11: '@typo3/backend/global-event-handler.js',
12: '@typo3/backend/action-dispatcher.js',
13: '@typo3/backend/element/immediate-action-element.js'
}"
/>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import $ from"jquery";import"@typo3/backend/element/icon-element.js";class DebugConsole{constructor(){this.settings={autoscroll:!0},$(()=>{this.createDom()})}static incrementInactiveTabCounter(t){if(!t.hasClass("active")){const e=t.find(".badge");let s=parseInt(e.text(),10);isNaN(s)&&(s=0),e.text(++s)}}add(t,e,s){this.attachToViewport();const n=$("<p />").html(t);void 0!==e&&e.length>0&&n.prepend($("<strong />").text(e)),void 0!==s&&0!==s.length||(s="Debug");const o="debugtab-"+s.toLowerCase().replace(/\W+/g,"-"),a=this.$consoleDom.find(".t3js-debuggroups"),i=this.$consoleDom.find(".t3js-debugcontent");let l=this.$consoleDom.find(".t3js-debuggroups li[data-identifier="+o+"]");0===l.length&&(l=$("<li />",{role:"presentation",class:"nav-item","data-identifier":o}).append($("<a />",{"aria-controls":o,"data-bs-toggle":"tab",class:"nav-link",href:"#"+o,role:"tab"}).text(s+" ").append($("<span />",{class:"badge"}))).on("shown.bs.tab",t=>{$(t.currentTarget).find(".badge").text("")}),a.append(l),i.append($("<div />",{role:"tabpanel",class:"tab-pane",id:o}).append($("<div />",{class:"t3js-messages messages"})))),0===a.find(".active").length&&a.find("a:first").tab("show"),DebugConsole.incrementInactiveTabCounter(l),this.incrementUnreadMessagesIfCollapsed();const d=$("#"+o+" .t3js-messages"),c=d.parent().hasClass("active");d.append(n),this.settings.autoscroll&&c&&d.scrollTop(d.prop("scrollHeight"))}createDom(){void 0===this.$consoleDom&&(this.$consoleDom=$("<div />",{id:"typo3-debug-console"}).append($("<div />",{class:"t3js-topbar topbar d-flex justify-content-between align-items-center"}).append($("<typo3-backend-icon />",{identifier:"actions-terminal",size:"small"}),$("<span />",{class:"flex-fill"}).text("TYPO3 Debug Console").append($("<span />",{class:"badge"})),$("<div />",{class:"t3js-buttons btn-group"})),$("<div />").append($("<div />",{role:"tabpanel"}).append($("<ul />",{class:"nav nav-tabs t3js-debuggroups",role:"tablist"})),$("<div />",{class:"tab-content t3js-debugcontent"}))),this.addButton($("<button />",{class:"btn btn-default btn-sm "+(this.settings.autoscroll?"active":""),title:TYPO3.lang["debuggerconsole.autoscroll"]}).append($("<typo3-backend-icon />",{identifier:"actions-magnet",size:"small"})),()=>{$(this).button("toggle"),this.settings.autoscroll=!this.settings.autoscroll}).addButton($("<button />",{class:"btn btn-default btn-sm",title:TYPO3.lang["debuggerconsole.toggle.collapse"]}).append($("<typo3-backend-icon />",{identifier:"actions-chevron-down",size:"small"})),t=>{let e=$(t.currentTarget),s=e.find("typo3-backend-icon"),n=this.$consoleDom.find(".t3js-topbar").next();n.toggle(),n.is(":visible")?(e.attr("title",TYPO3.lang["debuggerconsole.toggle.collapse"]),s.replaceWith($("<typo3-backend-icon />",{identifier:"actions-chevron-down",size:"small"})),this.resetGlobalUnreadCounter()):(e.attr("title",TYPO3.lang["debuggerconsole.toggle.expand"]),s.replaceWith($("<typo3-backend-icon />",{identifier:"actions-chevron-up",size:"small"})))}).addButton($("<button />",{class:"btn btn-default btn-sm",title:TYPO3.lang["debuggerconsole.clear"]}).append($("<typo3-backend-icon />",{identifier:"actions-undo",size:"small"})),()=>{this.flush()}).addButton($("<button />",{class:"btn btn-default btn-sm",title:TYPO3.lang["debuggerconsole.close"]}).append($("<typo3-backend-icon />",{identifier:"actions-close",size:"small"})),()=>{this.destroy(),this.createDom()}))}addButton(t,e){return t.on("click",e),this.$consoleDom.find(".t3js-buttons").append(t),this}attachToViewport(){const t=$(".t3js-scaffold-content");0===t.has(this.$consoleDom).length&&t.append(this.$consoleDom)}incrementUnreadMessagesIfCollapsed(){const t=this.$consoleDom.find(".t3js-topbar");if(t.next().is(":hidden")){const e=t.find(".badge");let s=parseInt(e.text(),10);isNaN(s)&&(s=0),e.text(++s)}}resetGlobalUnreadCounter(){this.$consoleDom.find(".t3js-topbar").find(".badge").text("")}flush(){const t=this.$consoleDom.find(".t3js-debuggroups"),e=this.$consoleDom.find(".t3js-debugcontent");t.children().remove(),e.children().remove()}destroy(){this.$consoleDom.remove(),this.$consoleDom=void 0}}const debugConsole=new DebugConsole;TYPO3.DebugConsole=debugConsole;export default debugConsole;
\ No newline at end of file
......@@ -17,9 +17,7 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Utility;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
/**
......@@ -36,39 +34,14 @@ class DebugUtility
*
* Directly echos out debug information as HTML (or plain in CLI context)
*/
public static function debug(mixed $var = '', string $header = 'Debug', string $group = 'Debug'): void
public static function debug(mixed $var = '', string $header = 'Debug'): void
{
// buffer the output of debug if no buffering started before
if (ob_get_level() === 0) {
ob_start();
}
if (!Environment::isCli()
&& ($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
&& ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()
) {
$debug = self::renderDump($var);
$debugPlain = PHP_EOL . self::renderDump($var, '', true, false);
$script = '
(function debug() {
var message = ' . GeneralUtility::quoteJSvalue($debug) . ',
messagePlain = ' . GeneralUtility::quoteJSvalue($debugPlain) . ',
header = ' . GeneralUtility::quoteJSvalue($header) . ',
group = ' . GeneralUtility::quoteJSvalue($group) . ';
if (top.TYPO3 && top.TYPO3.DebugConsole) {
top.TYPO3.DebugConsole.add(message, header, group);
} else {
var consoleMessage = [group, header, messagePlain].join(" | ");
if (typeof console === "object" && typeof console.log === "function") {
console.log(consoleMessage);
}
};
})();
';
echo GeneralUtility::wrapJS($script);
} else {
echo self::renderDump($var, $header);
}
echo self::renderDump($var, $header);
}
/**
......
.. include:: /Includes.rst.txt
.. _breaking-98069-1659536025:
=======================================
Breaking: #98069 - DebugConsole removed
=======================================
See :issue:`98069`
Description
===========
The DebugConsole comes from ExtJS times and was triggered when e.g. a request
failed to give a developer its response, including the stacktrace. Nowadays,
browsers offer a console allowing to investigate requests. Also, PHP debuggers
(e.g. xdebug) are commonly known and used, which makes the DebugConsole obsolete.
Impact
======
Triggering the DebugConsole is not possible anymore. Also, the PHP method
:php:`\TYPO3\CMS\Core\Utility\DebugUtility::debug()` always renders the plain
debug output to the client.
The 3rd argument :php:`$group` of the method
:php:`\TYPO3\CMS\Core\Utility\DebugUtility::debug()` is removed.
Affected installations
======================
All installations are affected.
Migration
=========
No migration is available.
.. index:: Backend, JavaScript, PHP-API, PartiallyScanned, ext:backend
......@@ -18,7 +18,7 @@ declare(strict_types=1);
// Short-hand debug function
// If you wish to use the debug()-function, and it does not output something,
// please edit the IP mask in TYPO3_CONF_VARS
function debug(mixed $variable = '', ?string $title = null, ?string $group = null): void
function debug(mixed $variable = '', ?string $title = null): void
{
if (!\TYPO3\CMS\Core\Utility\GeneralUtility::cmpIP(
\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REMOTE_ADDR'),
......@@ -27,5 +27,5 @@ function debug(mixed $variable = '', ?string $title = null, ?string $group = nul
) {
return;
}
\TYPO3\CMS\Core\Utility\DebugUtility::debug($variable, $title ?? '', $group ?? '');
\TYPO3\CMS\Core\Utility\DebugUtility::debug($variable, $title ?? '');
}
......@@ -83,4 +83,10 @@ return [
'Breaking-96107-DeprecatedFunctionalityRemoved.rst',
],
],
'TYPO3\CMS\Core\Utility\DebugUtility::debug' => [
'maximumNumberOfArguments' => 2,
'restFiles' => [
'Breaking-98069-DebugConsoleRemoved.rst',
],
],
];
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment