814bc1d7d48d2ac695cc74736732bb84b9e54a6b
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / DebugUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Class to handle debug
19 *
20 * @author Steffen Kamper <steffen@typo3.org>
21 */
22 class DebugUtility {
23
24 /**
25 * Template for debug output
26 *
27 * @var string
28 */
29 const DEBUG_TABLE_TEMPLATE = '
30 <table class="typo3-debug" border="0" cellpadding="0" cellspacing="0" bgcolor="white" style="border:0px; margin-top:3px; margin-bottom:3px;">
31 <tr>
32 <td style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;">%s</td>
33 </tr>
34 <tr>
35 <td>
36 %s
37 </td>
38 </tr>
39 </table>
40 ';
41
42 /**
43 * Debug
44 *
45 * @param string $var
46 * @param string $header
47 * @param string $group
48 * @return void
49 */
50 static public function debug($var = '', $header = '', $group = 'Debug') {
51 // buffer the output of debug if no buffering started before
52 if (ob_get_level() == 0) {
53 ob_start();
54 }
55 $debug = self::convertVariableToString($var);
56 if ($header) {
57 $debug = sprintf(self::DEBUG_TABLE_TEMPLATE, htmlspecialchars((string)$header), $debug);
58 }
59 if (TYPO3_MODE === 'BE' && !(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI)) {
60 $tabHeader = $header ?: 'Debug';
61 $script = '
62 (function debug() {
63 var debugMessage = ' . GeneralUtility::quoteJSvalue($debug) . ';
64 var header = ' . GeneralUtility::quoteJSvalue($tabHeader) . ';
65 var group = ' . GeneralUtility::quoteJSvalue($group) . ';
66
67 if (typeof Ext !== "object" && (top && typeof top.Ext !== "object")) {
68 document.write(debugMessage);
69 return;
70 }
71
72 if (top && typeof Ext !== "object") {
73 Ext = top.Ext;
74 }
75
76 Ext.onReady(function() {
77 var TYPO3ViewportInstance = null;
78
79 if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
80 TYPO3ViewportInstance = top.TYPO3.Backend;
81 } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
82 TYPO3ViewportInstance = TYPO3.Backend;
83 }
84
85 if (TYPO3ViewportInstance !== null) {
86 TYPO3ViewportInstance.DebugConsole.addTab(debugMessage, header, group);
87 } else {
88 document.write(debugMessage);
89 }
90 });
91 })();
92 ';
93 echo GeneralUtility::wrapJS($script);
94 } else {
95 echo $debug;
96 }
97 }
98
99 /**
100 * Converts a variable to a string
101 *
102 * @param mixed $variable
103 * @return string
104 */
105 static public function convertVariableToString($variable) {
106 if (is_array($variable)) {
107 $string = self::viewArray($variable);
108 } elseif (is_object($variable)) {
109 $string = '<strong>|Object:<pre>';
110 $string .= print_r($variable, TRUE);
111 $string .= '</pre>|</strong>';
112 } elseif ((string)$variable !== '') {
113 $string = '<strong>|' . htmlspecialchars((string)$variable) . '|</strong>';
114 } else {
115 $string = '<strong>| debug |</strong>';
116 }
117 return $string;
118 }
119
120 /**
121 * Opens a debug message inside a popup window
122 *
123 * @param mixed $debugVariable
124 * @param string $header
125 * @param string $group
126 */
127 static public function debugInPopUpWindow($debugVariable, $header = 'Debug', $group = 'Debug') {
128 $debugString = self::convertVariableToString($debugVariable);
129 $script = '
130 (function debug() {
131 var debugMessage = ' . GeneralUtility::quoteJSvalue($debugString) . ',
132 header = ' . GeneralUtility::quoteJSvalue($header) . ',
133 group = ' . GeneralUtility::quoteJSvalue($group) . ',
134
135 browserWindow = function(debug, header, group) {
136 var newWindow = window.open("", "TYPO3DebugWindow_" + group,
137 "width=600,height=400,menubar=0,toolbar=1,status=0,scrollbars=1,resizable=1"
138 );
139 if (newWindow.document.body.innerHTML) {
140 newWindow.document.body.innerHTML = newWindow.document.body.innerHTML +
141 "<hr />" + debugMessage;
142 } else {
143 newWindow.document.writeln(
144 "<html><head><title>Debug: " + header + "(" + group + ")</title></head>"
145 + "<body onload=\\"self.focus()\\">"
146 + debugMessage
147 + "</body></html>"
148 );
149 }
150 }
151
152 if (!top.Ext) {
153 browserWindow(debugMessage, header, group);
154 } else {
155 top.Ext.onReady(function() {
156 if (top && top.TYPO3 && top.TYPO3.Backend) {
157 top.TYPO3.Backend.DebugConsole.openBrowserWindow(header, debugMessage, group);
158 } else {
159 browserWindow(debugMessage, header, group);
160 }
161 });
162 }
163 })();
164 ';
165 echo GeneralUtility::wrapJS($script);
166 }
167
168 /**
169 * Displays the "path" of the function call stack in a string, using debug_backtrace
170 *
171 * @return string
172 */
173 static public function debugTrail() {
174 $trail = debug_backtrace();
175 $trail = array_reverse($trail);
176 array_pop($trail);
177 $path = array();
178 foreach ($trail as $dat) {
179 $pathFragment = $dat['class'] . $dat['type'] . $dat['function'];
180 // add the path of the included file
181 if (in_array($dat['function'], array('require', 'include', 'require_once', 'include_once'))) {
182 $pathFragment .= '(' . PathUtility::stripPathSitePrefix($dat['args'][0]) . '),' . PathUtility::stripPathSitePrefix($dat['file']);
183 }
184 $path[] = $pathFragment . '#' . $dat['line'];
185 }
186 return implode(' // ', $path);
187 }
188
189 /**
190 * Displays an array as rows in a table. Useful to debug output like an array of database records.
191 *
192 * @param mixed $rows Array of arrays with similar keys
193 * @param string $header Table header
194 * @param bool $returnHTML If TRUE, will return content instead of echo'ing out.
195 * @return void Outputs to browser.
196 */
197 static public function debugRows($rows, $header = '', $returnHTML = FALSE) {
198 if (is_array($rows)) {
199 $firstEl = reset($rows);
200 if (is_array($firstEl)) {
201 $headerColumns = array_keys($firstEl);
202 $tRows = array();
203 // Header:
204 $tRows[] = '<tr><td colspan="' . count($headerColumns) . '" style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;"><strong>' . htmlspecialchars($header) . '</strong></td></tr>';
205 $tCells = array();
206 foreach ($headerColumns as $key) {
207 $tCells[] = '
208 <td><font face="Verdana,Arial" size="1"><strong>' . htmlspecialchars($key) . '</strong></font></td>';
209 }
210 $tRows[] = '
211 <tr>' . implode('', $tCells) . '
212 </tr>';
213 // Rows:
214 foreach ($rows as $singleRow) {
215 $tCells = array();
216 foreach ($headerColumns as $key) {
217 $tCells[] = '
218 <td><font face="Verdana,Arial" size="1">' . (is_array($singleRow[$key]) ? self::debugRows($singleRow[$key], '', TRUE) : htmlspecialchars($singleRow[$key])) . '</font></td>';
219 }
220 $tRows[] = '
221 <tr>' . implode('', $tCells) . '
222 </tr>';
223 }
224 $table = '
225 <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">' . implode('', $tRows) . '
226 </table>';
227 if ($returnHTML) {
228 return $table;
229 } else {
230 echo $table;
231 }
232 } else {
233 debug('Empty array of rows', $header);
234 }
235 } else {
236 debug('No array of rows', $header);
237 }
238 }
239
240 /**
241 * Returns a string with a list of ascii-values for the first $characters characters in $string
242 *
243 * @param string $string String to show ASCII value for
244 * @param int $characters Number of characters to show
245 * @return string The string with ASCII values in separated by a space char.
246 */
247 static public function ordinalValue($string, $characters = 100) {
248 if (strlen($string) < $characters) {
249 $characters = strlen($string);
250 }
251 $valuestring = '';
252 for ($i = 0; $i < $characters; $i++) {
253 $valuestring .= ' ' . ord(substr($string, $i, 1));
254 }
255 return trim($valuestring);
256 }
257
258 /**
259 * Returns HTML-code, which is a visual representation of a multidimensional array
260 * use \TYPO3\CMS\Core\Utility\GeneralUtility::print_array() in order to print an array
261 * Returns FALSE if $array_in is not an array
262 *
263 * @param mixed $array_in Array to view
264 * @return string HTML output
265 */
266 static public function viewArray($array_in) {
267 if (is_array($array_in)) {
268 $result = '
269 <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">';
270 if (count($array_in) == 0) {
271 $result .= '<tr><td><font face="Verdana,Arial" size="1"><strong>EMPTY!</strong></font></td></tr>';
272 } else {
273 foreach ($array_in as $key => $val) {
274 $result .= '<tr>
275 <td valign="top"><font face="Verdana,Arial" size="1">' . htmlspecialchars((string)$key) . '</font></td>
276 <td>';
277 if (is_array($val)) {
278 $result .= self::viewArray($val);
279 } elseif (is_object($val)) {
280 $string = '';
281 if (method_exists($val, '__toString')) {
282 $string .= get_class($val) . ': ' . (string)$val;
283 } else {
284 $string .= print_r($val, TRUE);
285 }
286 $result .= '<font face="Verdana,Arial" size="1" color="red">' . nl2br(htmlspecialchars($string)) . '<br /></font>';
287 } else {
288 if (gettype($val) == 'object') {
289 $string = 'Unknown object';
290 } else {
291 $string = (string)$val;
292 }
293 $result .= '<font face="Verdana,Arial" size="1" color="red">' . nl2br(htmlspecialchars($string)) . '<br /></font>';
294 }
295 $result .= '</td>
296 </tr>';
297 }
298 }
299 $result .= '</table>';
300 } else {
301 $result = '<table border="1" cellpadding="1" cellspacing="0" bgcolor="white">
302 <tr>
303 <td><font face="Verdana,Arial" size="1" color="red">' . nl2br(htmlspecialchars((string)$array_in)) . '<br /></font></td>
304 </tr>
305 </table>';
306 }
307 // Output it as a string.
308 return $result;
309 }
310
311 /**
312 * Prints an array
313 *
314 * @param mixed $array_in Array to print visually (in a table).
315 * @return void
316 * @see viewArray()
317 */
318 static public function printArray($array_in) {
319 echo self::viewArray($array_in);
320 }
321
322 }