Commit 2d3134bc authored by Carsten  Rose's avatar Carsten Rose
Browse files

Feature #5347 / Error Message (Exception): hide technical informations, show it on click.

parent 79c9f836
......@@ -1305,3 +1305,28 @@ const AUTOCRON_COUNT = 'count';
// Annotate
const FABRIC_CSS_CLASS = 'fabric';
const EXCEPTION_TYPE = 'Type';
const EXCEPTION_FORM = 'Form';
const EXCEPTION_FORM_ELEMENT = 'Form Element';
const EXCEPTION_FORM_ELEMENT_COLUMN = 'Form Element Column';
const EXCEPTION_SQL_RAW = 'SQL before evaluation';
const EXCEPTION_SQL_FINAL = 'SQL final';
const EXCEPTION_SQL_PARAM_ARRAY = 'SQL Params';
const EXCEPTION_REPORT_COLUMN_INDEX = 'Report column index'; // Keyname of SQL-column processed at the moment.
const EXCEPTION_REPORT_COLUMN_NAME = 'Report column name'; // Keyname of SQL-column processed at the moment.
const EXCEPTION_REPORT_COLUMN_VALUE = 'Report column value'; // Keyname of SQL-column processed at the moment.
const EXCEPTION_REPORT_FULL_LEVEL = 'Report level key';
const EXCEPTION_SIP = 'current sip';
const EXCEPTION_PAGE_ID = 'Page Id';
const EXCEPTION_TT_CONTENT_UID = 'Content Id';
const EXCEPTION_EDIT_FORM = 'Edit form';
const EXCEPTION_TIMESTAMP = 'Timestamp';
const EXCEPTION_CODE = 'Code';
const EXCEPTION_MESSAGE = 'Message';
const EXCEPTION_FILE = 'File';
const EXCEPTION_LINE = 'Line';
const EXCEPTION_STACKTRACE = 'Stacktrace';
......@@ -15,11 +15,13 @@ require_once(__DIR__ . '/../store/Store.php');
require_once(__DIR__ . '/../report/Link.php');
require_once(__DIR__ . '/../database/Database.php');
require_once(__DIR__ . '/UserFormException.php');
require_once(__DIR__ . '/../helper/OnArray.php');
class AbstractException extends \Exception {
public $messageArray = array();
public $messageArrayDebug = array();
public $store = null;
protected $file = '';
......@@ -30,9 +32,9 @@ class AbstractException extends \Exception {
*/
public function formatException() {
$t3Vars = array();
$htmlForm = '';
$arrShow = $this->messageArray;
$htmlDebug = '';
$debug = '';
try {
// In a very early stage, it might be possible that Store can't be initialized: take care not to use it.
$store = Store::getInstance();
......@@ -47,100 +49,71 @@ class AbstractException extends \Exception {
$t3Vars = T3Info::getVars();
}
$html = '';
$arrShow[EXCEPTION_TIMESTAMP] = date('Y.m.d H:i:s O');
$arrShow[EXCEPTION_CODE] = $this->getCode();
$arrShow[EXCEPTION_MESSAGE] = $this->getMessage();
$this->messageArray['File'] = $this->getFile();
$this->messageArray['Line'] = $this->getLine();
$this->messageArray['Message'] = $this->getMessage();
$this->messageArray['Code'] = $this->getCode();
$this->messageArray['Timestamp'] = date('Y.m.d H:i:s O');
//TODO: 'Client' will remove any HTML Tags before displaying. Formatting needs to be solved together with 'Client',
// Respect mode: 'form load' (plain HTML), 'Ajax alert'
$this->messageArray['Stacktrace'] = $this->getTraceAsString();
// $this->messageArray['Stacktrace'] = $this->getTrace();
$html .= "Code: " . htmlspecialchars($this->messageArray['Code']) . "<br>";
unset($this->messageArray['Code']);
$html .= "Message: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray['Message'])) . "<br>";
// Form
if (isset($this->messageArray['Form']) && $this->messageArray['Form'] != '') {
$htmlForm = "Form: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray['Form'])) . "<br>";
}
if (isset($this->messageArray['Form Element']) && $this->messageArray['Form Element'] != '') {
$html .= "Form Element: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray['Form Element'])) . "<br>";
foreach ([EXCEPTION_FORM, EXCEPTION_FORM_ELEMENT, EXCEPTION_FORM_ELEMENT_COLUMN] as $key) {
if (isset($arrShow[$key])) {
if ($arrShow[$key] == '') {
unset($arrShow[$key]);
}
}
}
// Report
// if (isset($this->messageArray[SYSTEM_REPORT_COLUMN_INDEX])) {
// $html .= "Column index: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray[SYSTEM_REPORT_COLUMN_INDEX])) . "<br>";
// }
//
// if (isset($this->messageArray[SYSTEM_REPORT_COLUMN_INDEX])) {
// $html .= "Column index: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray[SYSTEM_REPORT_COLUMN_INDEX])) . "<br>";
// }
//
// if (isset($this->messageArray[SYSTEM_REPORT_COLUMN_NAME])) {
// $html .= "Column name: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray[SYSTEM_REPORT_COLUMN_NAME])) . "<br>";
// }
//
// if (isset($this->messageArray[SYSTEM_REPORT_COLUMN_VALUE])) {
// $html .= "Column value: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray[SYSTEM_REPORT_COLUMN_VALUE])) . "<br>";
// }
// $html .= "Code: " . htmlspecialchars($this->messageArray['Code']) . "<br>";
// $html .= "Message: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray['Message'])) . "<br>";
// Debug Information
if ($store !== null && Support::findInSet(SYSTEM_SHOW_DEBUG_INFO_YES, $store->getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM))) {
$type = $this->messageArray['Type'];
unset($this->messageArray['Type']);
$arrDebugShow = $this->messageArrayDebug;
$stackTrace = $this->messageArray['Stacktrace'];
unset($this->messageArray['Stacktrace']);
$arrDebugShow[EXCEPTION_SIP] = $store->getStore(STORE_SIP);
$arrDebugShow[EXCEPTION_PAGE_ID] = $t3Vars[TYPO3_PAGE_ID];
$arrDebugShow[EXCEPTION_TT_CONTENT_UID] = $t3Vars[TYPO3_TT_CONTENT_UID];
// In case there is a 'form' name given in SIP, we probably have a problem in a form and a direct link to
// edit the broken form will be helpful.
$storeSystem = $store->getStore(STORE_SYSTEM);
$this->messageArray['current sip'] = $store->getStore(STORE_SIP);
$this->messageArray['Page Id'] = $t3Vars[TYPO3_PAGE_ID];
$this->messageArray['Content Id'] = $t3Vars[TYPO3_TT_CONTENT_UID];
// In case there is a 'form' name given in SIP, we probably have a problem in a form and a direct link to edit the broken form is helpful.
if (!empty($storeSystem[SYSTEM_FORM])) {
$renderedUrl = $this->buildFormLink($storeSystem);
$htmlForm = "Form: " . $renderedUrl . "<br>";
$arrDebugShow[EXCEPTION_EDIT_FORM] = $this->buildFormLink($storeSystem);
}
$arrDebugHidden = array();
$arrDebugHidden[EXCEPTION_FILE] = $this->getFile();
$arrDebugHidden[EXCEPTION_LINE] = $this->getLine();
$arrDebugHidden[EXCEPTION_STACKTRACE] = $this->getTraceAsString();
// Layout
$debug = "<thead><tr><th>Exception</th><th>$type</th></tr></thead>";
foreach ($this->messageArray as $key => $value) {
// Array to string
if (is_array($value)) {
$value = var_export($value, true);
}
if (!empty($value)) {
$debug .= "<tr>" . "<td>$key</td>" . "<td>" . htmlspecialchars($value) . "</td>" . "</tr>";
}
}
// Optional existing arrays will be flatten.
$arrDebugShow = OnArray::varExportArray($arrDebugShow);
$arrDebugHidden = OnArray::varExportArray($arrDebugHidden);
// Sanitize any HTML content.
$arrDebugShow = OnArray::htmlentitiesOnArray($arrDebugShow);
$arrDebugHidden = OnArray::htmlentitiesOnArray($arrDebugHidden);
$debug = '<table class="table table-hover qfq-table-100">' . $debug . "</table>";
$htmlDebug = OnArray::arrayToHtmlTable($arrDebugShow, 'Debug', "table table-hover qfq-table-100");
$hidden = OnArray::arrayToHtmlTable($arrDebugHidden, 'Details', "table table-hover qfq-table-100");
// $hidden = 'mein test<br>und mehr content';
// Show / hide with just CSS: http://jsfiddle.net/t5Nf8/1/
$debug .= "<style>input[type=checkbox]:checked + label +p { display: none; }</style>";
$debug .= "<input type='checkbox' checked id='stacktrace'><label for='stacktrace'>&nbsp;Show/hide stacktrace</label><p>$stackTrace</p>";
// Stracktrace
$htmlDebug .= "<style>input[type=checkbox]:checked + label + table { display: none; }</style>" .
"<input type='checkbox' checked id='stacktrace'><label for='stacktrace'>&nbsp;Show/hide more details</label>$hidden";
}
$html = "<h2>Error</h2>" . Support::wrapTag('<p>', $html . $htmlForm);
// Sanitize any HTML content.
$arrShow = OnArray::htmlentitiesOnArray($arrShow);
$html = OnArray::arrayToHtmlTable($arrShow, 'Error', "table table-hover qfq-table-100");
// foreach ($show as $key => $value) {
// $html .= "$key: " . Support::wrapTag("<strong>", $value) . "<br>";
// }
$html = Support::wrapTag("<div class='warning'>", $html);
return $html . $debug;
return $html . $htmlDebug;
}
/**
* Build a FormEditor link to the broken form.
*/
......
......@@ -24,7 +24,7 @@ class CodeException extends AbstractException {
*/
public function formatMessage() {
$this->messageArray['Type'] = 'Code Exception';
$this->messageArrayDebug[EXCEPTION_TYPE] = 'Code Exception';
return parent::formatException();
}
......
......@@ -25,16 +25,17 @@ class DbException extends AbstractException {
*/
public function formatMessage() {
$this->messageArray['Type'] = 'Db Exception';
$this->messageArray['Form'] = Store::getVar(SYSTEM_FORM, STORE_SYSTEM);
$this->messageArray['Form Element'] = Store::getVar(SYSTEM_FORM_ELEMENT, STORE_SYSTEM);
$this->messageArray['Form Element Column'] = Store::getVar(SYSTEM_FORM_ELEMENT_COLUMN, STORE_SYSTEM);
$this->messageArray['SQL before evaluation'] = Store::getVar(SYSTEM_SQL_RAW, STORE_SYSTEM);
$this->messageArray['SQL final'] = Store::getVar(SYSTEM_SQL_FINAL, STORE_SYSTEM);
$this->messageArray['SQL Params'] = Store::getVar(SYSTEM_SQL_PARAM_ARRAY, STORE_SYSTEM);
$this->messageArray['Report level key'] = Store::getVar(SYSTEM_REPORT_FULL_LEVEL, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_TYPE] = 'Db Exception';
return parent::formatException();
$this->messageArray[EXCEPTION_FORM] = Store::getVar(SYSTEM_FORM, STORE_SYSTEM);
$this->messageArray[EXCEPTION_FORM_ELEMENT] = Store::getVar(SYSTEM_FORM_ELEMENT, STORE_SYSTEM);
$this->messageArray[EXCEPTION_FORM_ELEMENT_COLUMN] = Store::getVar(SYSTEM_FORM_ELEMENT_COLUMN, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_SQL_RAW] = Store::getVar(SYSTEM_SQL_RAW, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_SQL_FINAL] = Store::getVar(SYSTEM_SQL_FINAL, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_SQL_PARAM_ARRAY] = Store::getVar(SYSTEM_SQL_PARAM_ARRAY, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_REPORT_FULL_LEVEL] = Store::getVar(SYSTEM_REPORT_FULL_LEVEL, STORE_SYSTEM);
return parent::formatException();
}
}
......@@ -24,7 +24,7 @@ class DownloadException extends AbstractException {
*/
public function formatMessage() {
$this->messageArray['Type'] = 'Download Exception';
$this->messageArrayDebug[EXCEPTION_TYPE] = 'Download Exception';
return parent::formatException();
}
......
......@@ -24,7 +24,7 @@ class ShellException extends AbstractException {
*/
public function formatMessage() {
$this->messageArray['Type'] = 'Shell Exception';
$this->messageArrayDebug[EXCEPTION_TYPE] = 'Shell Exception';
return parent::formatException();
}
......
......@@ -25,10 +25,11 @@ class UserFormException extends AbstractException {
*/
public function formatMessage() {
$this->messageArray['Type'] = 'User Form Exception';
$this->messageArray['Form'] = Store::getVar(SYSTEM_FORM, STORE_SYSTEM);
$this->messageArray['Form Element'] = Store::getVar(SYSTEM_FORM_ELEMENT, STORE_SYSTEM);
$this->messageArray['Form Element Column'] = Store::getVar(SYSTEM_FORM_ELEMENT_COLUMN, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_TYPE] = 'User Form Exception';
$this->messageArrayDebug[EXCEPTION_FORM] = Store::getVar(SYSTEM_FORM, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_FORM_ELEMENT] = Store::getVar(SYSTEM_FORM_ELEMENT, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_FORM_ELEMENT_COLUMN] = Store::getVar(SYSTEM_FORM_ELEMENT_COLUMN, STORE_SYSTEM);
return parent::formatException();
}
......
......@@ -24,12 +24,13 @@ class UserReportException extends AbstractException {
*/
public function formatMessage() {
$this->messageArray['Type'] = 'User Report Exception';
$this->messageArray[SYSTEM_SQL_RAW] = htmlentities(Store::getVar(SYSTEM_SQL_RAW, STORE_SYSTEM));
$this->messageArray[SYSTEM_SQL_FINAL] = htmlentities(Store::getVar(SYSTEM_SQL_FINAL, STORE_SYSTEM));
$this->messageArray[SYSTEM_REPORT_COLUMN_INDEX] = htmlentities(Store::getVar(SYSTEM_REPORT_COLUMN_INDEX, STORE_SYSTEM));
$this->messageArray[SYSTEM_REPORT_COLUMN_NAME] = htmlentities(Store::getVar(SYSTEM_REPORT_COLUMN_NAME, STORE_SYSTEM));
$this->messageArray[SYSTEM_REPORT_COLUMN_VALUE] = htmlentities(Store::getVar(SYSTEM_REPORT_COLUMN_VALUE, STORE_SYSTEM));
$this->messageArrayDebug[EXCEPTION_TYPE] = 'User Report Exception';
$this->messageArrayDebug[EXCEPTION_SQL_RAW] = Store::getVar(SYSTEM_SQL_RAW, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_SQL_FINAL] = Store::getVar(SYSTEM_SQL_FINAL, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_REPORT_COLUMN_INDEX] = Store::getVar(SYSTEM_REPORT_COLUMN_INDEX, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_REPORT_COLUMN_NAME] = Store::getVar(SYSTEM_REPORT_COLUMN_NAME, STORE_SYSTEM);
$this->messageArrayDebug[EXCEPTION_REPORT_COLUMN_VALUE] = Store::getVar(SYSTEM_REPORT_COLUMN_VALUE, STORE_SYSTEM);
return parent::formatException();
}
......
......@@ -121,6 +121,38 @@ class OnArray {
return $arr;
}
/**
* Iterates over an key/value array. Each value will be 'var_export'.
*
* @param array $arr
* @return array
*/
public static function varExportArray(array $arr) {
foreach ($arr as $key => $value) {
$arr[$key] = var_export($value, true);
}
return $arr;
}
/**
* @param array $arr
* @param string $title
* @param string $class
*
* @return string
*/
public static function arrayToHtmlTable(array $arr, $title, $class) {
$html = '';
foreach ($arr as $key => $value) {
$html .= '<tr><td>' . $key . '</td><td>' . $value . '</td></tr>';
}
return "<table class='$class'><thead><tr><th colspan='2'>$title</th></tr></thead>$html</table>";
}
/**
* Split Array around $str to $arr around $delimiter. Escaped $delimiter will be preserved.
*
......
Markdown is supported
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