ed29c6c88e4f1d50d3128469bc57310eed5af1a4
[Packages/TYPO3.CMS.git] / t3lib / utility / class.t3lib_utility_debug.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010-2011 Steffen Kamper <steffen@typo3.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * Class to handle debug
30 *
31 * $Id: $
32 *
33 *
34 * @author Steffen Kamper <steffen@typo3.org>
35 * @package TYPO3
36 * @subpackage t3lib
37 */
38 class t3lib_utility_Debug {
39
40 /**
41 * Template for debug output
42 *
43 * @var string
44 */
45 const DEBUG_TABLE_TEMPLATE = '
46 <table class="typo3-debug" border="0" cellpadding="0" cellspacing="0" bgcolor="white" style="border:0px; margin-top:3px; margin-bottom:3px;">
47 <tr>
48 <td style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;">%s</td>
49 </tr>
50 <tr>
51 <td>
52 %s
53 </td>
54 </tr>
55 </table>
56 ';
57
58
59 public function debug($var = '', $header = '', $group = 'Debug') {
60 // buffer the output of debug if no buffering started before
61 if (ob_get_level() == 0) {
62 ob_start();
63 }
64
65 $debug = self::convertVariableToString($var);
66 if ($header) {
67 $debug = sprintf(self::DEBUG_TABLE_TEMPLATE, htmlspecialchars((string) $header), $debug);
68 }
69
70 if (TYPO3_MODE === 'BE') {
71 $debugString = self::prepareVariableForJavascript($debug, is_object($var));
72 $group = htmlspecialchars($group);
73
74 if ($header !== '') {
75 $tabHeader = htmlspecialchars($header);
76 } else {
77 $tabHeader = 'Debug';
78 }
79
80 $script = '
81 (function debug() {
82 var debugMessage = "' . $debugString . '";
83 var header = "' . $tabHeader . '";
84 var group = "' . $group . '";
85
86 if (typeof Ext !== "object" && (top && typeof top.Ext !== "object")) {
87 document.write(debugMessage);
88 return;
89 }
90
91 if (top && typeof Ext !== "object") {
92 Ext = top.Ext;
93 }
94
95 Ext.onReady(function() {
96 var TYPO3ViewportInstance = null;
97
98 if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
99 TYPO3ViewportInstance = top.TYPO3.Backend;
100 } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
101 TYPO3ViewportInstance = TYPO3.Backend;
102 }
103
104 if (TYPO3ViewportInstance !== null) {
105 TYPO3ViewportInstance.DebugConsole.addTab(debugMessage, header, group);
106 } else {
107 document.write(debugMessage);
108 }
109 });
110 })();
111 ';
112 echo t3lib_div::wrapJS($script);
113 } else {
114 echo $debug;
115 }
116 }
117
118 /**
119 * Replaces special characters for the usage inside javascript
120 *
121 * @param string $string
122 * @param boolean $asObject
123 * @return string
124 */
125 public static function prepareVariableForJavascript($string, $asObject) {
126 if ($asObject) {
127 $string = str_replace(array(
128 '"', '/', '<', "\n", "\r"
129 ), array(
130 '\"', '\/', '\<', '<br />', ''
131 ), $string);
132 } else {
133 $string = str_replace(array(
134 '"', '/', '<', "\n", "\r"
135 ), array(
136 '\"', '\/', '\<', '', ''
137 ), $string);
138 }
139
140 return $string;
141 }
142
143 /**
144 * Converts a variable to a string
145 *
146 * @param mixed $variable
147 * @return string
148 */
149 public static function convertVariableToString($variable) {
150 $string = '';
151 if (is_array($variable)) {
152 $string = self::viewArray($variable);
153 } elseif (is_object($variable)) {
154 $string = '<strong>|Object:<pre>';
155 $string .= print_r($variable, TRUE);
156 $string .= '</pre>|</strong>';
157 } elseif ((string) $variable !== '') {
158 $string = '<strong>|' . htmlspecialchars((string) $variable) . '|</strong>';
159 } else {
160 $string = '<strong>| debug |</strong>';
161 }
162
163 return $string;
164 }
165
166 /**
167 * Opens a debug message inside a popup window
168 *
169 * @param mixed $debugVariable
170 * @param string $header
171 * @param string $group
172 */
173 public static function debugInPopUpWindow($debugVariable, $header = 'Debug', $group = 'Debug') {
174 $debugString = self::prepareVariableForJavascript(
175 self::convertVariableToString($debugVariable),
176 is_object($debugVariable)
177 );
178
179 $script = '
180 (function debug() {
181 var debugMessage = "' . $debugString . '",
182 header = "' . htmlspecialchars($header) . '",
183 group = "' . htmlspecialchars($group) . '",
184
185 browserWindow = function(debug, header, group) {
186 var newWindow = window.open("", "TYPO3DebugWindow_" + group,
187 "width=600,height=400,menubar=0,toolbar=1,status=0,scrollbars=1,resizable=1"
188 );
189 if (newWindow.document.body.innerHTML) {
190 newWindow.document.body.innerHTML = newWindow.document.body.innerHTML +
191 "<hr />" + debugMessage;
192 } else {
193 newWindow.document.writeln(
194 "<html><head><title>Debug: " + header + "(" + group + ")</title></head>"
195 + "<body onload=\"self.focus()\">"
196 + debugMessage
197 + "</body></html>"
198 );
199 }
200 }
201
202 if (!top.Ext) {
203 browserWindow(debugMessage, header, group);
204 } else {
205 top.Ext.onReady(function() {
206 if (top && top.TYPO3 && top.TYPO3.Backend) {
207 top.TYPO3.Backend.DebugConsole.openBrowserWindow(header, debugMessage, group);
208 } else {
209 browserWindow(debugMessage, header, group);
210 }
211 });
212 }
213 })();
214 ';
215 echo t3lib_div::wrapJS($script);
216 }
217
218 /**
219 * Displays the "path" of the function call stack in a string, using debug_backtrace
220 *
221 * @return string
222 */
223 public function debugTrail() {
224 $trail = debug_backtrace();
225 $trail = array_reverse($trail);
226 array_pop($trail);
227
228 $path = array();
229 foreach ($trail as $dat) {
230 $path[] = $dat['class'] . $dat['type'] . $dat['function'] . '#' . $dat['line'];
231 }
232
233 return implode(' // ', $path);
234 }
235
236 /**
237 * Displays an array as rows in a table. Useful to debug output like an array of database records.
238 *
239 * @param mixed Array of arrays with similar keys
240 * @param string Table header
241 * @param boolean If TRUE, will return content instead of echo'ing out.
242 * @return void Outputs to browser.
243 */
244 public function debugRows($rows, $header = '', $returnHTML = FALSE) {
245 if (is_array($rows)) {
246 reset($rows);
247 $firstEl = current($rows);
248 if (is_array($firstEl)) {
249 $headerColumns = array_keys($firstEl);
250 $tRows = array();
251
252 // Header:
253 $tRows[] = '<tr><td colspan="' . count($headerColumns) .
254 '" style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;"><strong>' .
255 htmlspecialchars($header) . '</strong></td></tr>';
256 $tCells = array();
257 foreach ($headerColumns as $key) {
258 $tCells[] = '
259 <td><font face="Verdana,Arial" size="1"><strong>' . htmlspecialchars($key) . '</strong></font></td>';
260 }
261 $tRows[] = '
262 <tr>' . implode('', $tCells) . '
263 </tr>';
264
265 // Rows:
266 foreach ($rows as $singleRow) {
267 $tCells = array();
268 foreach ($headerColumns as $key) {
269 $tCells[] = '
270 <td><font face="Verdana,Arial" size="1">' .
271 (is_array($singleRow[$key]) ? self::debugRows($singleRow[$key], '', TRUE) : htmlspecialchars($singleRow[$key])) .
272 '</font></td>';
273 }
274 $tRows[] = '
275 <tr>' . implode('', $tCells) . '
276 </tr>';
277 }
278
279 $table = '
280 <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">' . implode('', $tRows) . '
281 </table>';
282 if ($returnHTML) {
283 return $table;
284 }
285 else
286 {
287 echo $table;
288 }
289 } else
290 {
291 debug('Empty array of rows', $header);
292 }
293 } else {
294 debug('No array of rows', $header);
295 }
296 }
297
298 /**
299 * Returns a string with a list of ascii-values for the first $characters characters in $string
300 *
301 * @param string String to show ASCII value for
302 * @param integer Number of characters to show
303 * @return string The string with ASCII values in separated by a space char.
304 * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::debug_ordvalue instead
305 */
306 public function ordinalValue($string, $characters = 100) {
307 if (strlen($string) < $characters) {
308 $characters = strlen($string);
309 }
310 for ($i = 0; $i < $characters; $i++) {
311 $valuestring .= ' ' . ord(substr($string, $i, 1));
312 }
313 return trim($valuestring);
314 }
315
316 /**
317 * Returns HTML-code, which is a visual representation of a multidimensional array
318 * use t3lib_div::print_array() in order to print an array
319 * Returns false if $array_in is not an array
320 *
321 * @param mixed Array to view
322 * @return string HTML output
323 */
324 public function viewArray($array_in) {
325 if (is_array($array_in)) {
326 $result = '
327 <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">';
328 if (count($array_in) == 0) {
329 $result .= '<tr><td><font face="Verdana,Arial" size="1"><strong>EMPTY!</strong></font></td></tr>';
330 } else {
331 foreach ($array_in as $key => $val) {
332 $result .= '<tr>
333 <td valign="top"><font face="Verdana,Arial" size="1">' . htmlspecialchars((string) $key) . '</font></td>
334 <td>';
335 if (is_array($val)) {
336 $result .= self::viewArray($val);
337 } elseif (is_object($val)) {
338 $string = '';
339 if (method_exists($val, '__toString')) {
340 $string .= get_class($val) . ': ' . (string) $val;
341 } else {
342 $string .= print_r($val, TRUE);
343 }
344 $result .= '<font face="Verdana,Arial" size="1" color="red">' .
345 nl2br(htmlspecialchars($string)) .
346 '<br /></font>';
347 } else {
348 if (gettype($val) == 'object') {
349 $string = 'Unknown object';
350 } else {
351 $string = (string) $val;
352 }
353 $result .= '<font face="Verdana,Arial" size="1" color="red">' .
354 nl2br(htmlspecialchars($string)) .
355 '<br /></font>';
356 }
357 $result .= '</td>
358 </tr>';
359 }
360 }
361 $result .= '</table>';
362 } else {
363 $result = '<table border="1" cellpadding="1" cellspacing="0" bgcolor="white">
364 <tr>
365 <td><font face="Verdana,Arial" size="1" color="red">' .
366 nl2br(htmlspecialchars((string) $array_in)) .
367 '<br /></font></td>
368 </tr>
369 </table>'; // Output it as a string.
370 }
371 return $result;
372 }
373
374 /**
375 * Prints an array
376 *
377 * @param mixed Array to print visually (in a table).
378 * @return void
379 * @see view_array()
380 */
381 public function printArray($array_in) {
382 echo self::viewArray($array_in);
383 }
384 }
385
386
387 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/utility/class.t3lib_utility_debug.php'])) {
388 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/utility/class.t3lib_utility_debug.php']);
389 }
390 ?>