Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   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   *
  32   * @author	  Steffen Kamper <steffen@typo3.org>
  33   * @package TYPO3
  34   * @subpackage t3lib
  35   */
  36  final class t3lib_utility_Debug {
  37  
  38  	 /**
  39  	  * Template for debug output
  40  	  *
  41  	  * @var string
  42  	  */
  43  	 const DEBUG_TABLE_TEMPLATE = '
  44  	 <table class="typo3-debug" border="0" cellpadding="0" cellspacing="0" bgcolor="white" style="border:0px; margin-top:3px; margin-bottom:3px;">
  45  	 	 <tr>
  46  	 	 	 <td style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;">%s</td>
  47  	 	 </tr>
  48  	 	 <tr>
  49  	 	 	 <td>
  50  	 	 	 %s
  51  	 	 	 </td>
  52  	 	 </tr>
  53  	 </table>
  54  	 ';
  55  
  56  
  57  	public static function debug($var = '', $header = '', $group = 'Debug') {
  58  	 	 	 // buffer the output of debug if no buffering started before
  59  	 	 if (ob_get_level() == 0) {
  60  	 	 	 ob_start();
  61  	 	 }
  62  
  63  	 	 $debug = self::convertVariableToString($var);
  64  	 	 if ($header) {
  65  	 	 	 $debug = sprintf(self::DEBUG_TABLE_TEMPLATE, htmlspecialchars((string) $header), $debug);
  66  	 	 }
  67  
  68  	 	 if (TYPO3_MODE === 'BE') {
  69  	 	 	 $debugString = self::prepareVariableForJavascript($debug, is_object($var));
  70  	 	 	 $group = htmlspecialchars($group);
  71  
  72  	 	 	 if ($header !== '') {
  73  	 	 	 	 $tabHeader = htmlspecialchars($header);
  74  	 	 	 } else {
  75  	 	 	 	 $tabHeader = 'Debug';
  76  	 	 	 }
  77  
  78  	 	 	 $script = '
  79  	 	 	 	 (function debug() {
  80  	 	 	 	 	 var debugMessage = "' . $debugString . '";
  81  	 	 	 	 	 var header = "' . $tabHeader . '";
  82  	 	 	 	 	 var group = "' . $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 t3lib_div::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  	  */
 123  	public static function prepareVariableForJavascript($string, $asObject) {
 124  	 	 if ($asObject) {
 125  	 	 	 $string = str_replace(array(
 126  	 	 	 	 '"', '/', '<', "\n", "\r"
 127  	 	 	 ), array(
 128  	 	 	 	 '\"', '\/', '\<', '<br />', ''
 129  	 	 	 ), $string);
 130  	 	 } else {
 131  	 	 	 $string = str_replace(array(
 132  	 	 	 	 '"', '/', '<', "\n", "\r"
 133  	 	   ), array(
 134  	 	 	 	 '\"', '\/', '\<', '', ''
 135  	 	 	 ), $string);
 136  	 	 }
 137  
 138  	 	 return $string;
 139  	 }
 140  
 141  	 /**
 142  	  * Converts a variable to a string
 143  	  *
 144  	  * @param mixed $variable
 145  	  * @return string
 146  	  */
 147  	public static function convertVariableToString($variable) {
 148  	 	 $string = '';
 149  	 	 if (is_array($variable)) {
 150  	 	 	 $string = self::viewArray($variable);
 151  	 	 } elseif (is_object($variable)) {
 152  	 	 	 $string = '<strong>|Object:<pre>';
 153  	 	 	 $string .= print_r($variable, TRUE);
 154  	 	 	 $string .= '</pre>|</strong>';
 155  	 	 } elseif ((string) $variable !== '') {
 156  	 	 	 $string = '<strong>|' . htmlspecialchars((string) $variable) . '|</strong>';
 157  	 	 } else {
 158  	 	 	 $string = '<strong>| debug |</strong>';
 159  	 	 }
 160  
 161  	 	 return $string;
 162  	 }
 163  
 164  	 /**
 165  	  * Opens a debug message inside a popup window
 166  	  *
 167  	  * @param mixed $debugVariable
 168  	  * @param string $header
 169  	  * @param string $group
 170  	  */
 171  	public static function debugInPopUpWindow($debugVariable, $header = 'Debug', $group = 'Debug') {
 172  	 	 $debugString = self::prepareVariableForJavascript(
 173  	 	 	 self::convertVariableToString($debugVariable),
 174  	 	 	 is_object($debugVariable)
 175  	 	 );
 176  
 177  	 	 $script = '
 178  	 	 	 (function debug() {
 179  	 	 	 	 var debugMessage = "' . $debugString . '",
 180  	 	 	 	 	 header = "' . htmlspecialchars($header) . '",
 181  	 	 	 	 	 group = "' . htmlspecialchars($group) . '",
 182  
 183  	 	 	 	 	 browserWindow = function(debug, header, group) {
 184  	 	 	 	 	 	 var newWindow = window.open("", "TYPO3DebugWindow_" + group,
 185  	 	 	 	 	 	 	 "width=600,height=400,menubar=0,toolbar=1,status=0,scrollbars=1,resizable=1"
 186  	 	 	 	 	 	 );
 187  	 	 	 	 	 	 if (newWindow.document.body.innerHTML) {
 188  	 	 	 	 	 	 	 newWindow.document.body.innerHTML = newWindow.document.body.innerHTML +
 189  	 	 	 	 	 	 	 	 "<hr />" + debugMessage;
 190  	 	 	 	 	 	 } else {
 191  	 	 	 	 	 	 	 newWindow.document.writeln(
 192  	 	 	 	 	 	 	 	 "<html><head><title>Debug: " + header + "(" + group + ")</title></head>"
 193  	 	 	 	 	 	 	 	 + "<body onload=\"self.focus()\">"
 194  	 	 	 	 	 	 	 	 + debugMessage
 195  	 	 	 	 	 	 	 	 + "</body></html>"
 196  	 	 	 	 	 	 	 );
 197  	 	 	 	 	 	 }
 198  	 	 	 	 	 }
 199  
 200  	 	 	 	 if (!top.Ext) {
 201  	 	 	 	 	 browserWindow(debugMessage, header, group);
 202  	 	 	 	 } else {
 203  	 	 	 	 	 top.Ext.onReady(function() {
 204  	 	 	 	 	 	 if (top && top.TYPO3 && top.TYPO3.Backend) {
 205  	 	 	 	 	 	 	 top.TYPO3.Backend.DebugConsole.openBrowserWindow(header, debugMessage, group);
 206  	 	 	 	 	 	 } else {
 207  	 	 	 	 	 	 	 browserWindow(debugMessage, header, group);
 208  	 	 	 	 	 	 }
 209  	 	 	 	 	 });
 210  	 	 	 	 }
 211  	 	 	 })();
 212  	 	 ';
 213  	 	 echo t3lib_div::wrapJS($script);
 214  	 }
 215  
 216  	 /**
 217  	  * Displays the "path" of the function call stack in a string, using debug_backtrace
 218  	  *
 219  	  * @return	 string
 220  	  */
 221  	public static function debugTrail() {
 222  	 	 $trail = debug_backtrace();
 223  	 	 $trail = array_reverse($trail);
 224  	 	 array_pop($trail);
 225  
 226  	 	 $path = array();
 227  	 	 foreach ($trail as $dat) {
 228  	 	 	 $pathFragment = $dat['class'] . $dat['type'] . $dat['function'];
 229  	 	 	 	 // add the path of the included file
 230  	 	 	 if (in_array($dat['function'], array('require', 'include', 'require_once', 'include_once'))) {
 231  	 	 	 	 $pathFragment .= '(' . substr($dat['args'][0], strlen(PATH_site)) . '),' . substr($dat['file'], strlen(PATH_site));
 232  	 	 	 }
 233  	 	 	 $path[] = $pathFragment . '#' . $dat['line'];
 234  	 	 }
 235  
 236  	 	 return implode(' // ', $path);
 237  	 }
 238  
 239  	 /**
 240  	  * Displays an array as rows in a table. Useful to debug output like an array of database records.
 241  	  *
 242  	  * @param	 mixed	 	 Array of arrays with similar keys
 243  	  * @param	 string	 	 Table header
 244  	  * @param	 boolean	 	 If TRUE, will return content instead of echo'ing out.
 245  	  * @return	 void	 	 Outputs to browser.
 246  	  */
 247  	public static function debugRows($rows, $header = '', $returnHTML = FALSE) {
 248  	 	 if (is_array($rows)) {
 249  	 	 	 $firstEl = reset($rows);
 250  	 	 	 if (is_array($firstEl)) {
 251  	 	 	 	 $headerColumns = array_keys($firstEl);
 252  	 	 	 	 $tRows = array();
 253  
 254  	 	 	 	 	 // Header:
 255  	 	 	 	 $tRows[] = '<tr><td colspan="' . count($headerColumns) .
 256  	 	 	 	 	 	    '" style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;"><strong>' .
 257  	 	 	 	 	 	    htmlspecialchars($header) . '</strong></td></tr>';
 258  	 	 	 	 $tCells = array();
 259  	 	 	 	 foreach ($headerColumns as $key) {
 260  	 	 	 	 	 $tCells[] = '
 261  	 	 	 	 	 	 	 <td><font face="Verdana,Arial" size="1"><strong>' . htmlspecialchars($key) . '</strong></font></td>';
 262  	 	 	 	 }
 263  	 	 	 	 $tRows[] = '
 264  	 	 	 	 	 	 <tr>' . implode('', $tCells) . '
 265  	 	 	 	 	 	 </tr>';
 266  
 267  	 	 	 	 	 // Rows:
 268  	 	 	 	 foreach ($rows as $singleRow) {
 269  	 	 	 	 	 $tCells = array();
 270  	 	 	 	 	 foreach ($headerColumns as $key) {
 271  	 	 	 	 	 	 $tCells[] = '
 272  	 	 	 	 	 	 	 <td><font face="Verdana,Arial" size="1">' .
 273  	 	 	 	 	 	 	 	 	 (is_array($singleRow[$key]) ? self::debugRows($singleRow[$key], '', TRUE) : htmlspecialchars($singleRow[$key])) .
 274  	 	 	 	 	 	 	 	 	 '</font></td>';
 275  	 	 	 	 	 }
 276  	 	 	 	 	 $tRows[] = '
 277  	 	 	 	 	 	 <tr>' . implode('', $tCells) . '
 278  	 	 	 	 	 	 </tr>';
 279  	 	 	 	 }
 280  
 281  	 	 	 	 $table = '
 282  	 	 	 	 	 <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">' . implode('', $tRows) . '
 283  	 	 	 	 	 </table>';
 284  	 	 	 	 if ($returnHTML) {
 285  	 	 	 	 	 return $table;
 286  	 	 	 	 }
 287  	 	 	 	 else
 288  	 	 	 	 {
 289  	 	 	 	 	 echo $table;
 290  	 	 	 	 }
 291  	 	 	 } else
 292  	 	 	 {
 293  	 	 	 	 debug('Empty array of rows', $header);
 294  	 	 	 }
 295  	 	 } else {
 296  	 	 	 debug('No array of rows', $header);
 297  	 	 }
 298  	 }
 299  
 300  	 /**
 301  	  * Returns a string with a list of ascii-values for the first $characters characters in $string
 302  	  *
 303  	  * @param	 string	 	 String to show ASCII value for
 304  	  * @param	 integer	 	 Number of characters to show
 305  	  * @return	 string	 	 The string with ASCII values in separated by a space char.
 306  	  */
 307  	public static function ordinalValue($string, $characters = 100) {
 308  	 	 if (strlen($string) < $characters) {
 309  	 	 	 $characters = strlen($string);
 310  	 	 }
 311  	 	 for ($i = 0; $i < $characters; $i++) {
 312  	 	 	 $valuestring .= ' ' . ord(substr($string, $i, 1));
 313  	 	 }
 314  	 	 return trim($valuestring);
 315  	 }
 316  
 317  	 /**
 318  	  * Returns HTML-code, which is a visual representation of a multidimensional array
 319  	  * use t3lib_div::print_array() in order to print an array
 320  	  * Returns FALSE if $array_in is not an array
 321  	  *
 322  	  * @param	 mixed	 	 Array to view
 323  	  * @return	 string	 	 HTML output
 324  	  */
 325  	public static function viewArray($array_in) {
 326  	 	 if (is_array($array_in)) {
 327  	 	 	 $result = '
 328  	 	 	 <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">';
 329  	 	 	 if (count($array_in) == 0) {
 330  	 	 	 	 $result .= '<tr><td><font face="Verdana,Arial" size="1"><strong>EMPTY!</strong></font></td></tr>';
 331  	 	 	 } else {
 332  	 	 	 	 foreach ($array_in as $key => $val) {
 333  	 	 	 	 	 $result .= '<tr>
 334  	 	 	 	 	 	 <td valign="top"><font face="Verdana,Arial" size="1">' . htmlspecialchars((string) $key) . '</font></td>
 335  	 	 	 	 	 	 <td>';
 336  	 	 	 	 	 if (is_array($val)) {
 337  	 	 	 	 	 	 $result .= self::viewArray($val);
 338  	 	 	 	 	 } elseif (is_object($val)) {
 339  	 	 	 	 	 	 $string = '';
 340  	 	 	 	 	 	 if (method_exists($val, '__toString')) {
 341  	 	 	 	 	 	 	 $string .= get_class($val) . ': ' . (string) $val;
 342  	 	 	 	 	 	 } else {
 343  	 	 	 	 	 	 	 $string .= print_r($val, TRUE);
 344  	 	 	 	 	 	 }
 345  	 	 	 	 	 	 $result .= '<font face="Verdana,Arial" size="1" color="red">' .
 346  	 	 	 	 	 	 	 	    nl2br(htmlspecialchars($string)) .
 347  	 	 	 	 	 	 	 	    '<br /></font>';
 348  	 	 	 	 	 } else {
 349  	 	 	 	 	 	 if (gettype($val) == 'object') {
 350  	 	 	 	 	 	 	 $string = 'Unknown object';
 351  	 	 	 	 	 	 } else {
 352  	 	 	 	 	 	 	 $string = (string) $val;
 353  	 	 	 	 	 	 }
 354  	 	 	 	 	 	 $result .= '<font face="Verdana,Arial" size="1" color="red">' .
 355  	 	 	 	 	 	 	 	    nl2br(htmlspecialchars($string)) .
 356  	 	 	 	 	 	 	 	    '<br /></font>';
 357  	 	 	 	 	 }
 358  	 	 	 	 	 $result .= '</td>
 359  	 	 	 	 	 </tr>';
 360  	 	 	 	 }
 361  	 	 	 }
 362  	 	 	 $result .= '</table>';
 363  	 	 } else {
 364  	 	 	 $result = '<table border="1" cellpadding="1" cellspacing="0" bgcolor="white">
 365  	 	 	 	 <tr>
 366  	 	 	 	 	 <td><font face="Verdana,Arial" size="1" color="red">' .
 367  	 	 	 	 	   nl2br(htmlspecialchars((string) $array_in)) .
 368  	 	 	 	 	   '<br /></font></td>
 369  	 	 	 	 </tr>
 370  	 	 	 </table>'; // Output it as a string.
 371  	 	 }
 372  	 	 return $result;
 373  	 }
 374  
 375  	 /**
 376  	  * Prints an array
 377  	  *
 378  	  * @param	 mixed	 	 Array to print visually (in a table).
 379  	  * @return	 void
 380  	  * @see viewArray()
 381  	  */
 382  	public static function printArray($array_in) {
 383  	 	 echo self::viewArray($array_in);
 384  	 }
 385  }
 386  
 387  ?>