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