Fixed bug #15589: Move debug functions to own utility class
authorSteffen Kamper <info@sk-typo3.de>
Mon, 6 Sep 2010 11:57:16 +0000 (11:57 +0000)
committerSteffen Kamper <info@sk-typo3.de>
Mon, 6 Sep 2010 11:57:16 +0000 (11:57 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@8763 709f56b5-9817-0410-a4d7-c38de5d9e867

17 files changed:
ChangeLog
t3lib/class.t3lib_db.php
t3lib/class.t3lib_fullsearch.php
t3lib/class.t3lib_readmail.php
t3lib/class.t3lib_refindex.php
t3lib/class.t3lib_timetrack.php
t3lib/core_autoload.php
t3lib/extjs/class.t3lib_extjs_extdirectdebug.php
t3lib/utility/class.t3lib_utility_debug.php [new file with mode: 0644]
typo3/sysext/cms/tslib/class.tslib_content.php
typo3/sysext/cms/tslib/media/scripts/example_itemArrayProcFunc.php
typo3/sysext/cms/tslib/media/scripts/example_keepRollover.php
typo3/sysext/em/mod1/class.em_index.php
typo3/sysext/impexp/class.tx_impexp.php
typo3/sysext/lowlevel/class.tx_lowlevel_cleaner.php
typo3/sysext/statictemplates/media/scripts/example_itemArrayProcFunc.php
typo3/sysext/statictemplates/media/scripts/example_keepRollover.php

index 5d69142..f901aef 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-09-06  Steffen Kamper  <steffen@typo3.org>
+
+       * Fixed bug #15589: Move debug functions to own utility class
+
 2010-09-05  Steffen Gebert  <steffen@steffen-gebert.de>
 
        * Fixed bug #15562: PHP warning for str_pad() in t3lib_div::cmpIPv4() (Thanks to Markus Klein)
index f67f2ef..d256312 100644 (file)
@@ -1448,7 +1448,7 @@ class t3lib_DB {
                                        'caller' => 't3lib_DB::' . $func,
                                        'ERROR' => $error,
                                        'lastBuiltQuery' => ($query ? $query : $this->debug_lastBuiltQuery),
-                                       'debug_backtrace' => t3lib_div::debug_trail(),
+                                       'debug_backtrace' => t3lib_utility_Debug::debugTrail(),
                                ),
                                $func,
                                is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debug')) ? '' : 'DB Error'
@@ -1523,7 +1523,7 @@ class t3lib_DB {
                }
 
                $error = $this->sql_error();
-               $trail = t3lib_div::debug_trail();
+               $trail = t3lib_utility_Debug::debugTrail();
 
                $explain_tables = array();
                $explain_output = array();
@@ -1578,7 +1578,7 @@ class t3lib_DB {
                                }
 
                                if ($explainMode == 1) {
-                                       t3lib_div::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
+                                       t3lib_utility_Debug::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
                                } elseif ($explainMode == 2) {
                                        $GLOBALS['TT']->setTSselectQuery($data);
                                }
index 7857473..de03b4c 100644 (file)
@@ -542,7 +542,7 @@ class t3lib_fullsearch {
                        case 'explain':
                        default:
                                while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
-                                       $out.='<BR>'.t3lib_div::view_array($row);
+                                       $out .= '<br />' . t3lib_utility_Debug::viewArray($row);
                                }
                                $cPR['header']='Explain SQL query';
                                $cPR['content']=$out;
index f00ba68..9e305bf 100644 (file)
@@ -393,7 +393,7 @@ class t3lib_readmail {
         * The extended version of the extractMailHeader() which will also parse all the content body into an array and further process the header fields and decode content etc. Returns every part of the mail ready to go.
         *
         * @param       string          Raw email input.
-        * @return      array           Multidimensional array with all parts of the message organized nicely. Use t3lib_div::debug() to analyse it visually.
+        * @return      array           Multidimensional array with all parts of the message organized nicely. Use t3lib_utility_Debug::debug() to analyse it visually.
         */
        function fullParse($content)    {
                        // *************************
index 16ffdc5..00a3bb6 100644 (file)
@@ -1028,7 +1028,6 @@ class t3lib_refindex {
                                        $Err = 'Record '.$tableName.':'.$recdat['uid'].' had '.$result['addedNodes'].' added indexes and '.$result['deletedNodes'].' deleted indexes';
                                        $errors[]= $Err;
                                        if ($cli_echo) echo $Err.LF;
-                                       #$errors[] = t3lib_div::view_array($result);
                                }
                        }
 
index d5dba33..a21a1ea 100644 (file)
@@ -442,7 +442,7 @@ class t3lib_timeTrack {
                                }
                        }
                        if ($flag_queries && is_array($data['selectQuery'])) {
-                               $msgArr[] = t3lib_div::view_array($data['selectQuery']);
+                               $msgArr[] = t3lib_utility_Debug::viewArray($data['selectQuery']);
                        }
                        if ($flag_content && strcmp($data['content'],'')) {
                                $maxlen = 120;
index ce55bf3..268da7f 100644 (file)
@@ -133,6 +133,7 @@ $t3libClasses = array(
        't3lib_utility_client' => PATH_t3lib . 'utility/class.t3lib_utility_client.php',
        't3lib_utility_http' => PATH_t3lib . 'utility/class.t3lib_utility_http.php',
        't3lib_utility_mail' => PATH_t3lib . 'utility/class.t3lib_utility_mail.php',
+       't3lib_utility_debug' => PATH_t3lib . 'utility/class.t3lib_utility_debug.php',
        't3lib_spritemanager' => PATH_t3lib . 'class.t3lib_spritemanager.php',
        't3lib_spritemanager_spritegenerator' => PATH_t3lib . 'spritemanager/class.t3lib_spritemanager_spritegenerator.php',
        't3lib_spritemanager_spriteicongenerator' => PATH_t3lib . 'interfaces/interface.t3lib_spritemanager_spriteicongenerator.php',
index 97f4fcf..71ac2b7 100644 (file)
@@ -57,7 +57,7 @@ final class t3lib_extjs_ExtDirectDebug {
        public static function toString() {\r
                $messagesAsString = '';\r
                if (count(self::$debugMessages)) {\r
-                       $messagesAsString = t3lib_div::view_array(self::$debugMessages);\r
+                       $messagesAsString = t3lib_utility_Debug::viewArray(self::$debugMessages);\r
                }\r
 \r
                return $messagesAsString;\r
diff --git a/t3lib/utility/class.t3lib_utility_debug.php b/t3lib/utility/class.t3lib_utility_debug.php
new file mode 100644 (file)
index 0000000..1947653
--- /dev/null
@@ -0,0 +1,309 @@
+<?php
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2010 Steffen Kamper <steffen@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Class to handle debug
+ *
+ * $Id: $
+ *
+ *
+ * @author      Steffen Kamper <steffen@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_utility_Debug {
+
+       /**
+        * Template for debug output
+        *
+        * @var string
+        */
+       const DEBUG_TABLE_TEMPLATE = '
+       <table class="typo3-debug" border="0" cellpadding="0" cellspacing="0" bgcolor="white" style="border:0px; margin-top:3px; margin-bottom:3px;">
+               <tr>
+                       <td style="background-color:#bbbbbb; font-family: verdana,arial; font-weight: bold; font-size: 10px;">%s</td>
+               </tr>
+               <tr>
+                       <td>
+                       %s
+                       </td>
+               </tr>
+       </table>
+       ';
+
+
+       public function debug($var = '', $header = '', $group = 'Debug') {
+               // buffer the output of debug if no buffering started before
+               if (ob_get_level() == 0) {
+                       ob_start();
+               }
+               $debug = '';
+
+               if (is_array($var)) {
+                       $debug .= self::viewArray($var);
+               } elseif (is_object($var)) {
+                       $debug .= '<strong>|Object:<pre>';
+                       $debug .= print_r($var, TRUE);
+                       $debug .= '</pre>|</strong>';
+               } elseif ((string) $var !== '') {
+                       $debug .= '<strong>|' . htmlspecialchars((string) $var) . '|</strong>';
+               } else {
+                       $debug .= '<strong>| debug |</strong>';
+               }
+
+               if ($header) {
+                       $debug = sprintf(self::DEBUG_TABLE_TEMPLATE, htmlspecialchars((string) $header), $debug);
+               }
+
+               if (TYPO3_MODE === 'BE') {
+                       $group = htmlspecialchars($group);
+
+                       if ($header !== '') {
+                               $tabHeader = htmlspecialchars($header);
+                       } else {
+                               $tabHeader = 'Debug';
+                       }
+
+                       if (is_object($var)) {
+                               $debug = str_replace(array (
+                                       '"', '/', '<', "\n", "\r"
+                               ), array (
+                                       '\"', '\/', '\<', '<br />', ''
+                               ), $debug);
+                       } else {
+                               $debug = str_replace(array (
+                                       '"', '/', '<', "\n", "\r"
+                               ), array (
+                                       '\"', '\/', '\<', '', ''
+                               ), $debug);
+                       }
+
+                       $script = '
+                               (function debug() {
+                                       var debugMessage = "' . $debug . '";
+                                       var header = "' . $tabHeader . '";
+                                       var group = "' . $group . '";
+
+                                       if (typeof Ext !== "object" && (top && typeof top.Ext !== "object")) {
+                                               document.write(debugMessage);
+                                               return;
+                                       }
+
+                                       if (top && typeof Ext !== "object") {
+                                               Ext = top.Ext;
+                                       }
+
+                                       Ext.onReady(function() {
+                                               var TYPO3ViewportInstance = null;
+
+                                               if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
+                                                       TYPO3ViewportInstance = top.TYPO3.Backend;
+                                               } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
+                                                       TYPO3ViewportInstance = TYPO3.Backend;
+                                               }
+
+                                               if (TYPO3ViewportInstance !== null) {
+                                                       TYPO3ViewportInstance.DebugConsole.addTab(debugMessage, header, group);
+                                               } else {
+                                                       document.write(debugMessage);
+                                               }
+                                       });
+                               })();
+                       ';
+                       echo t3lib_div::wrapJS($script);
+               } else {
+                       echo $debug;
+               }
+       }
+
+       /**
+        * Displays the "path" of the function call stack in a string, using debug_backtrace
+        *
+        * @return      string
+        */
+       public function debugTrail() {
+               $trail = debug_backtrace();
+               $trail = array_reverse($trail);
+               array_pop($trail);
+
+               $path = array ();
+               foreach ($trail as $dat) {
+                       $path[] = $dat['class'] . $dat['type'] . $dat['function'] . '#' . $dat['line'];
+               }
+
+               return implode(' // ', $path);
+       }
+
+       /**
+        * Displays an array as rows in a table. Useful to debug output like an array of database records.
+        *
+        * @param       mixed           Array of arrays with similar keys
+        * @param       string          Table header
+        * @param       boolean         If TRUE, will return content instead of echo'ing out.
+        * @return      void            Outputs to browser.
+        */
+       public function debugRows($rows, $header = '', $returnHTML = FALSE) {
+               if (is_array($rows)) {
+                       reset($rows);
+                       $firstEl = current($rows);
+                       if (is_array($firstEl)) {
+                               $headerColumns = array_keys($firstEl);
+                               $tRows = array ();
+
+                               // Header:
+                               $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>';
+                               $tCells = array ();
+                               foreach ($headerColumns as $key) {
+                                       $tCells[] = '
+                                                       <td><font face="Verdana,Arial" size="1"><strong>' . htmlspecialchars($key) . '</strong></font></td>';
+                               }
+                               $tRows[] = '
+                                               <tr>' . implode('', $tCells) . '
+                                               </tr>';
+
+                               // Rows:
+                               foreach ($rows as $singleRow) {
+                                       $tCells = array ();
+                                       foreach ($headerColumns as $key) {
+                                               $tCells[] = '
+                                                       <td><font face="Verdana,Arial" size="1">' .
+                                                       (is_array($singleRow[$key]) ? self::debugRows($singleRow[$key], '', TRUE) : htmlspecialchars($singleRow[$key])) .
+                                                       '</font></td>';
+                                       }
+                                       $tRows[] = '
+                                               <tr>' . implode('', $tCells) . '
+                                               </tr>';
+                               }
+
+                               $table = '
+                                       <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">' . implode('', $tRows) . '
+                                       </table>';
+                               if ($returnHTML)
+                                       return $table;
+                               else
+                                       echo $table;
+                       } else
+                               debug('Empty array of rows', $header);
+               } else {
+                       debug('No array of rows', $header);
+               }
+       }
+
+       /**
+        * Returns a string with a list of ascii-values for the first $characters characters in $string
+        *
+        * @param       string          String to show ASCII value for
+        * @param       integer         Number of characters to show
+        * @return      string          The string with ASCII values in separated by a space char.
+        * @deprecated since TYPO3 4.5 - Use t3lib_utility_Debug::debug_ordvalue instead
+        */
+       public function ordinalValue($string, $characters = 100) {
+               if (strlen($string) < $characters)
+                       $characters = strlen($string);
+               for ($i = 0; $i < $characters; $i++) {
+                       $valuestring .= ' ' . ord(substr($string, $i, 1));
+               }
+               return trim($valuestring);
+       }
+
+       /**
+        * Returns HTML-code, which is a visual representation of a multidimensional array
+        * use t3lib_div::print_array() in order to print an array
+        * Returns false if $array_in is not an array
+        *
+        * @param       mixed           Array to view
+        * @return      string          HTML output
+        */
+       public function viewArray($array_in) {
+               if (is_array($array_in)) {
+                       $result = '
+                       <table border="1" cellpadding="1" cellspacing="0" bgcolor="white">';
+                       if (count($array_in) == 0) {
+                               $result .= '<tr><td><font face="Verdana,Arial" size="1"><strong>EMPTY!</strong></font></td></tr>';
+                       } else {
+                               foreach ($array_in as $key => $val) {
+                                       $result .= '<tr>
+                                               <td valign="top"><font face="Verdana,Arial" size="1">' . htmlspecialchars((string) $key) . '</font></td>
+                                               <td>';
+                                       if (is_array($val)) {
+                                               $result .= self::viewArray($val);
+                                       } elseif (is_object($val)) {
+                                               $string = '';
+                                               if (method_exists($val, '__toString')) {
+                                                       $string .= get_class($val) . ': ' . (string) $val;
+                                               } else {
+                                                       $string .= print_r($val, TRUE);
+                                               }
+                                               $result .= '<font face="Verdana,Arial" size="1" color="red">' .
+                                                       nl2br(htmlspecialchars($string)) .
+                                                       '<br /></font>';
+                                       } else {
+                                               if (gettype($val) == 'object') {
+                                                       $string = 'Unknown object';
+                                               } else {
+                                                       $string = (string) $val;
+                                               }
+                                               $result .= '<font face="Verdana,Arial" size="1" color="red">' .
+                                                       nl2br(htmlspecialchars($string)) .
+                                                       '<br /></font>';
+                                       }
+                                       $result .= '</td>
+                                       </tr>';
+                               }
+                       }
+                       $result .= '</table>';
+               } else {
+                       $result = '<table border="1" cellpadding="1" cellspacing="0" bgcolor="white">
+                               <tr>
+                                       <td><font face="Verdana,Arial" size="1" color="red">' .
+                                       nl2br(htmlspecialchars((string) $array_in)) .
+                                       '<br /></font></td>
+                               </tr>
+                       </table>'; // Output it as a string.
+               }
+               return $result;
+       }
+
+       /**
+        * Prints an array
+        *
+        * @param       mixed           Array to print visually (in a table).
+        * @return      void
+        * @see view_array()
+        */
+       public function printArray($array_in) {
+               echo self::viewArray($array_in);
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/utility/class.t3lib_utility_debug.php'])    {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/utility/class.t3lib_utility_debug.php']);
+}
+?>
\ No newline at end of file
index 5062bb4..3b258ed 100644 (file)
@@ -3138,7 +3138,7 @@ class tslib_cObj {
                                        $conf['altText.'] = $conf['alttext.'];
                                }
                        }
-                       
+
                        $altParam = $this->getAltParam($conf);
                        $theValue = '<img src="'.htmlspecialchars($GLOBALS['TSFE']->absRefPrefix.t3lib_div::rawUrlEncodeFP($info[3])).'" width="'.$info[0].'" height="'.$info[1].'"'.$this->getBorderAttr(' border="'.intval($conf['border']).'"').(($conf['params'] || is_array($conf['params.']))?' '.$this->stdWrap($conf['params'],$conf['params.']):'').($altParam).' />';
                        if ($conf['linkWrap'])  {
@@ -5509,7 +5509,6 @@ class tslib_cObj {
                                                                                                        unlink($file);
                                                                                                }
                                                                                        }
-                                                                                               //      t3lib_div::print_array($GLOBALS['TSFE']->tmpl->fileCache[$hash]);
                                                                                }
                                                                        }
                                                                }
@@ -5743,13 +5742,13 @@ class tslib_cObj {
                                        case 'debug':
                                                switch((string)$key)    {
                                                        case 'rootLine':
-                                                               $retVal = t3lib_div::view_array($GLOBALS['TSFE']->tmpl->rootLine);
+                                                               $retVal = t3lib_utility_Debug::viewArray($GLOBALS['TSFE']->tmpl->rootLine);
                                                        break;
                                                        case 'fullRootLine':
-                                                               $retVal = t3lib_div::view_array($GLOBALS['TSFE']->rootLine);
+                                                               $retVal = t3lib_utility_Debug::viewArray($GLOBALS['TSFE']->rootLine);
                                                        break;
                                                        case 'data':
-                                                               $retVal = t3lib_div::view_array($this->data);
+                                                               $retVal = t3lib_utility_Debug::viewArray($this->data);
                                                        break;
                                                }
                                        break;
index 677ded3..e71d57d 100755 (executable)
@@ -113,8 +113,8 @@ function user_IProcFuncTest($I,$conf)       {
        if ($conf['debug'])     {
                        // Outputting for debug example:
                echo 'ITEM: <h2>'.htmlspecialchars($itemRow['uid'].': '.$itemRow['title']).'</h2>';
-               t3lib_div::debug($itemRow);
-               t3lib_div::debug($I);
+               t3lib_utility_Debug::debug($itemRow);
+               t3lib_utility_Debug::debug($I);
                echo '<hr />';
        }
                // Returns:
index ff0e4c0..039bc78 100755 (executable)
@@ -83,8 +83,8 @@ function user_keepRolloverAtOnClick($I,$conf) {
        if ($conf['debug'])     {
                        // Outputting for debug example:
                echo 'ITEM: <h2>'.htmlspecialchars($itemRow['uid'].': '.$itemRow['title']).'</h2>';
-               t3lib_div::debug($itemRow);
-               t3lib_div::debug($I);
+               t3lib_utility_Debug::debug($itemRow);
+               t3lib_utility_Debug::debug($I);
                echo '<hr />';
        }
 
index 48ffdb6..eade00b 100644 (file)
@@ -3181,7 +3181,7 @@ EXTENSION KEYS:
                                                $GLOBALS['LANG']->getLL('extInfoArray_dev_relevant') . '</td>
                                        <td>' . (is_array($techInfo['NSerrors']) ?
                                                (!t3lib_div::inList($this->nameSpaceExceptions, $extKey) ?
-                                                       t3lib_div::view_array($techInfo['NSerrors']) :
+                                                       t3lib_utility_Debug::viewArray($techInfo['NSerrors']) :
                                                        $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('extInfoArray_exception'))) : '') . '</td>' .
                                        $this->helpCol('NSerrors') . '</tr>';
 
@@ -3445,7 +3445,7 @@ EXTENSION KEYS:
                        $cells[] = '<td>'.(is_array($techInfo['errors']) ? $GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])) : '').'</td>';
                        $cells[] = '<td>'.(is_array($techInfo['NSerrors']) ?
                                                (!t3lib_div::inList($this->nameSpaceExceptions, $extKey) ?
-                                                       t3lib_div::view_array($techInfo['NSerrors']) :
+                                                       t3lib_utility_Debug::viewArray($techInfo['NSerrors']) :
                                                        $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('extInfoArray_exception'))) : '') . '</td>';
                } elseif ($this->MOD_SETTINGS['display_details']==5)    {
                        $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo);
index 1201a67..2b3d6d0 100755 (executable)
@@ -3329,7 +3329,7 @@ class tx_impexp {
         * @return      string          HTML print of error log
         */
        function printErrorLog()        {
-               return count($this->errorLog) ? t3lib_div::view_array($this->errorLog) : '';
+               return count($this->errorLog) ? t3lib_utility_Debug::viewArray($this->errorLog) : '';
        }
 }
 
index c7f4f9e..ac0b7d7 100644 (file)
@@ -211,7 +211,7 @@ debug($contentTreeData);
                                        } else {
                                                $output.='<input type="submit" name="_EDIT" value="EDIT" />';
                                                $output.='<input type="submit" name="_DELETE" value="DELETE" onclick="return confirm(\'Are you sure you wish to delete?\');" />';
-                                               $output.=t3lib_div::view_array($rec);
+                                               $output.= t3lib_utility_Debug::viewArray($rec);
                                                $output.=md5(implode($rec));
                                        }
                                } else {
index fcfa392..cac3f40 100644 (file)
@@ -113,8 +113,8 @@ function user_IProcFuncTest($I,$conf)       {
        if ($conf['debug'])     {
                        // Outputting for debug example:
                echo 'ITEM: <h2>'.htmlspecialchars($itemRow['uid'].': '.$itemRow['title']).'</h2>';
-               t3lib_div::debug($itemRow);
-               t3lib_div::debug($I);
+               t3lib_utility_Debug::debug($itemRow);
+               t3lib_utility_Debug::debug($I);
                echo '<hr />';
        }
                // Returns:
index edc5eaf..462d8b2 100644 (file)
@@ -83,8 +83,8 @@ function user_keepRolloverAtOnClick($I,$conf) {
        if ($conf['debug'])     {
                        // Outputting for debug example:
                echo 'ITEM: <h2>'.htmlspecialchars($itemRow['uid'].': '.$itemRow['title']).'</h2>';
-               t3lib_div::debug($itemRow);
-               t3lib_div::debug($I);
+               t3lib_utility_Debug::debug($itemRow);
+               t3lib_utility_Debug::debug($I);
                echo '<hr />';
        }