Advertisement
justin_hanekom

dBug.php

Feb 1st, 2025
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.15 KB | None | 0 0
  1. <?php
  2. /*********************************************************************************************************************\
  3.  * LAST UPDATE
  4.  * ============
  5.  * August 6th, 2012
  6.  *
  7.  *
  8.  * AUTHOR
  9.  * =============
  10.  * Kwaku Otchere
  11.  *
  12.  * AFTERMARKET HACKER
  13.  * ==================
  14.  * Josh Sherman
  15.  *
  16.  * Thanks to Andrew Hewitt ([email protected]) for the idea and suggestion
  17.  *
  18.  * All the credit goes to ColdFusion's brilliant cfdump tag
  19.  * Hope the next version of PHP can implement this or have something similar
  20.  * I love PHP, but var_dump BLOWS!!!
  21.  *
  22.  * FOR DOCUMENTATION AND MORE EXAMPLES: VISIT http://dbug.ospinto.com
  23.  *
  24.  *
  25.  * PURPOSE
  26.  * =============
  27.  * Dumps/Displays the contents of a variable in a colored tabular format
  28.  * Based on the idea, javascript and css code of Macromedia's ColdFusion cfdump tag
  29.  * A much better presentation of a variable's contents than PHP's var_dump and print_r functions
  30.  *
  31.  *
  32.  * USAGE
  33.  * =============
  34.  * new dBug ( variable [,forceType] );
  35.  * example:
  36.  * new dBug ( $myVariable );
  37.  *
  38.  *
  39.  * if the optional "forceType" string is given, the variable supplied to the
  40.  * function is forced to have that forceType type.
  41.  * example: new dBug( $myVariable , "array" );
  42.  * will force $myVariable to be treated and dumped as an array type,
  43.  * even though it might originally have been a string type, etc.
  44.  *
  45.  * NOTE!
  46.  * ==============
  47.  * forceType is REQUIRED for dumping an xml string or xml file
  48.  * new dBug ( $strXml, "xml" );
  49.  *
  50. \*********************************************************************************************************************/
  51.  
  52. class dBug {
  53.  
  54.     var $xmlDepth=array();
  55.     var $xmlCData;
  56.     var $xmlSData;
  57.     var $xmlDData;
  58.     var $xmlCount=0;
  59.     var $xmlAttrib;
  60.     var $xmlName;
  61.     var $arrType=array("array","object","resource","boolean","NULL");
  62.     var $bInitialized = false;
  63.     var $bCollapsed = false;
  64.     var $arrHistory = array();
  65.  
  66.     //constructor
  67.     function dBug($var,$forceType="",$bCollapsed=false) {
  68.         //include js and css scripts
  69.         if(!defined('BDBUGINIT')) {
  70.             define("BDBUGINIT", TRUE);
  71.             $this->initJSandCSS();
  72.         }
  73.         $arrAccept=array("array","object","xml"); //array of variable types that can be "forced"
  74.         $this->bCollapsed = $bCollapsed;
  75.         if(in_array($forceType,$arrAccept))
  76.             $this->{"varIs".ucfirst($forceType)}($var);
  77.         else
  78.             $this->checkType($var);
  79.     }
  80.  
  81.     //get variable name
  82.     function getVariableName() {
  83.         $arrBacktrace = debug_backtrace();
  84.  
  85.         //possible 'included' functions
  86.         $arrInclude = array("include","include_once","require","require_once");
  87.  
  88.         //check for any included/required files. if found, get array of the last included file (they contain the right line numbers)
  89.         for($i=count($arrBacktrace)-1; $i>=0; $i--) {
  90.             $arrCurrent = $arrBacktrace[$i];
  91.             if(array_key_exists("function", $arrCurrent) &&
  92.                 (in_array($arrCurrent["function"], $arrInclude) || (0 != strcasecmp($arrCurrent["function"], "dbug"))))
  93.                 continue;
  94.  
  95.             $arrFile = $arrCurrent;
  96.  
  97.             break;
  98.         }
  99.  
  100.         if(isset($arrFile)) {
  101.             $arrLines = file($arrFile["file"]);
  102.             $code = $arrLines[($arrFile["line"]-1)];
  103.  
  104.             //find call to dBug class
  105.             preg_match('/\bnew dBug\s*\(\s*(.+)\s*\);/i', $code, $arrMatches);
  106.  
  107.             return $arrMatches[1];
  108.         }
  109.         return "";
  110.     }
  111.  
  112.     //create the main table header
  113.     function makeTableHeader($type,$header,$colspan=2) {
  114.         if(!$this->bInitialized) {
  115.             $header = $this->getVariableName() . " (" . $header . ")";
  116.             $this->bInitialized = true;
  117.         }
  118.         $str_i = ($this->bCollapsed) ? "style=\"font-style:italic\" " : "";
  119.  
  120.         echo "<table cellspacing=2 cellpadding=3 class=\"dBug_".$type."\">
  121.                 <tr>
  122.                     <td ".$str_i."class=\"dBug_".$type."Header\" colspan=".$colspan." onClick='dBug_toggleTable(this)'>".$header."</td>
  123.                 </tr>";
  124.     }
  125.  
  126.     //create the table row header
  127.     function makeTDHeader($type,$header) {
  128.         $str_d = ($this->bCollapsed) ? " style=\"display:none\"" : "";
  129.         echo "<tr".$str_d.">
  130.                 <td valign=\"top\" onClick='dBug_toggleRow(this)' class=\"dBug_".$type."Key\">".$header."</td>
  131.                 <td>";
  132.     }
  133.  
  134.     //close table row
  135.     function closeTDRow() {
  136.         return "</td></tr>\n";
  137.     }
  138.  
  139.     //error
  140.     function  error($type) {
  141.         $error="Error: Variable cannot be a";
  142.         // this just checks if the type starts with a vowel or "x" and displays either "a" or "an"
  143.         if(in_array(substr($type,0,1),array("a","e","i","o","u","x")))
  144.             $error.="n";
  145.         return ($error." ".$type." type");
  146.     }
  147.  
  148.     //check variable type
  149.     function checkType($var) {
  150.         switch(gettype($var)) {
  151.             case "resource":
  152.                 $this->varIsResource($var);
  153.                 break;
  154.             case "object":
  155.                 $this->varIsObject($var);
  156.                 break;
  157.             case "array":
  158.                 $this->varIsArray($var);
  159.                 break;
  160.             case "NULL":
  161.                 $this->varIsNULL();
  162.                 break;
  163.             case "boolean":
  164.                 $this->varIsBoolean($var);
  165.                 break;
  166.             default:
  167.                 $var=($var=="") ? "[empty string]" : $var;
  168.                 echo "<table cellspacing=0><tr>\n<td>".$var."</td>\n</tr>\n</table>\n";
  169.                 break;
  170.         }
  171.     }
  172.  
  173.     //if variable is a NULL type
  174.     function varIsNULL() {
  175.         echo "NULL";
  176.     }
  177.  
  178.     //if variable is a boolean type
  179.     function varIsBoolean($var) {
  180.         $var=($var==1) ? "TRUE" : "FALSE";
  181.         echo $var;
  182.     }
  183.  
  184.     //if variable is an array type
  185.     function varIsArray($var) {
  186.         $var_ser = serialize($var);
  187.         array_push($this->arrHistory, $var_ser);
  188.  
  189.         $this->makeTableHeader("array","array");
  190.         if(is_array($var)) {
  191.             foreach($var as $key=>$value) {
  192.                 $this->makeTDHeader("array",$key);
  193.  
  194.                 //check for recursion
  195.                 if(is_array($value)) {
  196.                     $var_ser = serialize($value);
  197.                     if(in_array($var_ser, $this->arrHistory, TRUE))
  198.                         $value = "*RECURSION*";
  199.                 }
  200.  
  201.                 if(in_array(gettype($value),$this->arrType))
  202.                     $this->checkType($value);
  203.                 else {
  204.                     $value=(trim($value)=="") ? "[empty string]" : $value;
  205.                     echo $value;
  206.                 }
  207.                 echo $this->closeTDRow();
  208.             }
  209.         }
  210.         else echo "<tr><td>".$this->error("array").$this->closeTDRow();
  211.         array_pop($this->arrHistory);
  212.         echo "</table>";
  213.     }
  214.  
  215.     //if variable is an object type
  216.     function varIsObject($var) {
  217.         $var_ser = serialize($var);
  218.         array_push($this->arrHistory, $var_ser);
  219.         $this->makeTableHeader("object","object");
  220.  
  221.         if(is_object($var)) {
  222.             $arrObjVars=get_object_vars($var);
  223.             foreach($arrObjVars as $key=>$value) {
  224.  
  225.                 $value=(!is_object($value) && !is_array($value) && trim($value)=="") ? "[empty string]" : $value;
  226.                 $this->makeTDHeader("object",$key);
  227.  
  228.                 //check for recursion
  229.                 if(is_object($value)||is_array($value)) {
  230.                     $var_ser = serialize($value);
  231.                     if(in_array($var_ser, $this->arrHistory, TRUE)) {
  232.                         $value = (is_object($value)) ? "*RECURSION* -> $".get_class($value) : "*RECURSION*";
  233.  
  234.                     }
  235.                 }
  236.                 if(in_array(gettype($value),$this->arrType))
  237.                     $this->checkType($value);
  238.                 else echo $value;
  239.                 echo $this->closeTDRow();
  240.             }
  241.             $arrObjMethods=get_class_methods(get_class($var));
  242.             foreach($arrObjMethods as $key=>$value) {
  243.                 $this->makeTDHeader("object",$value);
  244.                 echo "[function]".$this->closeTDRow();
  245.             }
  246.         }
  247.         else echo "<tr><td>".$this->error("object").$this->closeTDRow();
  248.         array_pop($this->arrHistory);
  249.         echo "</table>";
  250.     }
  251.  
  252.     //if variable is a resource type
  253.     function varIsResource($var) {
  254.         $this->makeTableHeader("resourceC","resource",1);
  255.         echo "<tr>\n<td>\n";
  256.         switch(get_resource_type($var)) {
  257.             case "fbsql result":
  258.             case "mssql result":
  259.             case "msql query":
  260.             case "pgsql result":
  261.             case "sybase-db result":
  262.             case "sybase-ct result":
  263.             case "mysql result":
  264.                 $db=current(explode(" ",get_resource_type($var)));
  265.                 $this->varIsDBResource($var,$db);
  266.                 break;
  267.             case "gd":
  268.                 $this->varIsGDResource($var);
  269.                 break;
  270.             case "xml":
  271.                 $this->varIsXmlResource($var);
  272.                 break;
  273.             default:
  274.                 echo get_resource_type($var).$this->closeTDRow();
  275.                 break;
  276.         }
  277.         echo $this->closeTDRow()."</table>\n";
  278.     }
  279.  
  280.     //if variable is a database resource type
  281.     function varIsDBResource($var,$db="mysql") {
  282.         if($db == "pgsql")
  283.             $db = "pg";
  284.         if($db == "sybase-db" || $db == "sybase-ct")
  285.             $db = "sybase";
  286.         $arrFields = array("name","type","flags");
  287.         $numrows=call_user_func($db."_num_rows",$var);
  288.         $numfields=call_user_func($db."_num_fields",$var);
  289.         $this->makeTableHeader("resource",$db." result",$numfields+1);
  290.         echo "<tr><td class=\"dBug_resourceKey\">&nbsp;</td>";
  291.         for($i=0;$i<$numfields;$i++) {
  292.             $field_header = "";
  293.             for($j=0; $j<count($arrFields); $j++) {
  294.                 $db_func = $db."_field_".$arrFields[$j];
  295.                 if(function_exists($db_func)) {
  296.                     $fheader = call_user_func($db_func, $var, $i). " ";
  297.                     if($j==0)
  298.                         $field_name = $fheader;
  299.                     else
  300.                         $field_header .= $fheader;
  301.                 }
  302.             }
  303.             $field[$i]=call_user_func($db."_fetch_field",$var,$i);
  304.             echo "<td class=\"dBug_resourceKey\" title=\"".$field_header."\">".$field_name."</td>";
  305.         }
  306.         echo "</tr>";
  307.         for($i=0;$i<$numrows;$i++) {
  308.             $row=call_user_func($db."_fetch_array",$var,constant(strtoupper($db)."_ASSOC"));
  309.             echo "<tr>\n";
  310.             echo "<td class=\"dBug_resourceKey\">".($i+1)."</td>";
  311.             for($k=0;$k<$numfields;$k++) {
  312.                 $tempField=$field[$k]->name;
  313.                 $fieldrow=$row[($field[$k]->name)];
  314.                 $fieldrow=($fieldrow=="") ? "[empty string]" : $fieldrow;
  315.                 echo "<td>".$fieldrow."</td>\n";
  316.             }
  317.             echo "</tr>\n";
  318.         }
  319.         echo "</table>";
  320.         if($numrows>0)
  321.             call_user_func($db."_data_seek",$var,0);
  322.     }
  323.  
  324.     //if variable is an image/gd resource type
  325.     function varIsGDResource($var) {
  326.         $this->makeTableHeader("resource","gd",2);
  327.         $this->makeTDHeader("resource","Width");
  328.         echo imagesx($var).$this->closeTDRow();
  329.         $this->makeTDHeader("resource","Height");
  330.         echo imagesy($var).$this->closeTDRow();
  331.         $this->makeTDHeader("resource","Colors");
  332.         echo imagecolorstotal($var).$this->closeTDRow();
  333.         echo "</table>";
  334.     }
  335.  
  336.     //if variable is an xml type
  337.     function varIsXml($var) {
  338.         $this->varIsXmlResource($var);
  339.     }
  340.  
  341.     //if variable is an xml resource type
  342.     function varIsXmlResource($var) {
  343.         $xml_parser=xml_parser_create();
  344.         xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
  345.         xml_set_element_handler($xml_parser,array(&$this,"xmlStartElement"),array(&$this,"xmlEndElement"));
  346.         xml_set_character_data_handler($xml_parser,array(&$this,"xmlCharacterData"));
  347.         xml_set_default_handler($xml_parser,array(&$this,"xmlDefaultHandler"));
  348.  
  349.         $this->makeTableHeader("xml","xml document",2);
  350.         $this->makeTDHeader("xml","xmlRoot");
  351.  
  352.         //attempt to open xml file
  353.         $bFile=(!($fp=@fopen($var,"r"))) ? false : true;
  354.  
  355.         //read xml file
  356.         if($bFile) {
  357.             while($data=str_replace("\n","",fread($fp,4096)))
  358.                 $this->xmlParse($xml_parser,$data,feof($fp));
  359.         }
  360.         //if xml is not a file, attempt to read it as a string
  361.         else {
  362.             if(!is_string($var)) {
  363.                 echo $this->error("xml").$this->closeTDRow()."</table>\n";
  364.                 return;
  365.             }
  366.             $data=$var;
  367.             $this->xmlParse($xml_parser,$data,1);
  368.         }
  369.  
  370.         echo $this->closeTDRow()."</table>\n";
  371.  
  372.     }
  373.  
  374.     //parse xml
  375.     function xmlParse($xml_parser,$data,$bFinal) {
  376.         if (!xml_parse($xml_parser,$data,$bFinal)) {
  377.             die(sprintf("XML error: %s at line %d\n",
  378.                 xml_error_string(xml_get_error_code($xml_parser)),
  379.                 xml_get_current_line_number($xml_parser)));
  380.         }
  381.     }
  382.  
  383.     //xml: inititiated when a start tag is encountered
  384.     function xmlStartElement($parser,$name,$attribs) {
  385.         $this->xmlAttrib[$this->xmlCount]=$attribs;
  386.         $this->xmlName[$this->xmlCount]=$name;
  387.         $this->xmlSData[$this->xmlCount]='$this->makeTableHeader("xml","xml element",2);';
  388.         $this->xmlSData[$this->xmlCount].='$this->makeTDHeader("xml","xmlName");';
  389.         $this->xmlSData[$this->xmlCount].='echo "<strong>'.$this->xmlName[$this->xmlCount].'</strong>".$this->closeTDRow();';
  390.         $this->xmlSData[$this->xmlCount].='$this->makeTDHeader("xml","xmlAttributes");';
  391.         if(count($attribs)>0)
  392.             $this->xmlSData[$this->xmlCount].='$this->varIsArray($this->xmlAttrib['.$this->xmlCount.']);';
  393.         else
  394.             $this->xmlSData[$this->xmlCount].='echo "&nbsp;";';
  395.         $this->xmlSData[$this->xmlCount].='echo $this->closeTDRow();';
  396.         $this->xmlCount++;
  397.     }
  398.  
  399.     //xml: initiated when an end tag is encountered
  400.     function xmlEndElement($parser,$name) {
  401.         for($i=0;$i<$this->xmlCount;$i++) {
  402.             eval($this->xmlSData[$i]);
  403.             $this->makeTDHeader("xml","xmlText");
  404.             echo (!empty($this->xmlCData[$i])) ? $this->xmlCData[$i] : "&nbsp;";
  405.             echo $this->closeTDRow();
  406.             $this->makeTDHeader("xml","xmlComment");
  407.             echo (!empty($this->xmlDData[$i])) ? $this->xmlDData[$i] : "&nbsp;";
  408.             echo $this->closeTDRow();
  409.             $this->makeTDHeader("xml","xmlChildren");
  410.             unset($this->xmlCData[$i],$this->xmlDData[$i]);
  411.         }
  412.         echo $this->closeTDRow();
  413.         echo "</table>";
  414.         $this->xmlCount=0;
  415.     }
  416.  
  417.     //xml: initiated when text between tags is encountered
  418.     function xmlCharacterData($parser,$data) {
  419.         $count=$this->xmlCount-1;
  420.         if(!empty($this->xmlCData[$count]))
  421.             $this->xmlCData[$count].=$data;
  422.         else
  423.             $this->xmlCData[$count]=$data;
  424.     }
  425.  
  426.     //xml: initiated when a comment or other miscellaneous texts is encountered
  427.     function xmlDefaultHandler($parser,$data) {
  428.         //strip '<!--' and '-->' off comments
  429.         $data=str_replace(array("&lt;!--","--&gt;"),"",htmlspecialchars($data));
  430.         $count=$this->xmlCount-1;
  431.         if(!empty($this->xmlDData[$count]))
  432.             $this->xmlDData[$count].=$data;
  433.         else
  434.             $this->xmlDData[$count]=$data;
  435.     }
  436.  
  437.     function initJSandCSS() {
  438.         echo <<<SCRIPTS
  439.             <script language="JavaScript">
  440.             /* code modified from ColdFusion's cfdump code */
  441.                 function dBug_toggleRow(source) {
  442.                     var target = (document.all) ? source.parentElement.cells[1] : source.parentNode.lastChild;
  443.                     dBug_toggleTarget(target,dBug_toggleSource(source));
  444.                 }
  445.  
  446.                 function dBug_toggleSource(source) {
  447.                     if (source.style.fontStyle=='italic') {
  448.                         source.style.fontStyle='normal';
  449.                         source.title='click to collapse';
  450.                         return 'open';
  451.                     } else {
  452.                         source.style.fontStyle='italic';
  453.                         source.title='click to expand';
  454.                         return 'closed';
  455.                     }
  456.                 }
  457.  
  458.                 function dBug_toggleTarget(target,switchToState) {
  459.                     target.style.display = (switchToState=='open') ? '' : 'none';
  460.                 }
  461.  
  462.                 function dBug_toggleTable(source) {
  463.                     var switchToState=dBug_toggleSource(source);
  464.                     if(document.all) {
  465.                         var table=source.parentElement.parentElement;
  466.                         for(var i=1;i<table.rows.length;i++) {
  467.                             target=table.rows[i];
  468.                             dBug_toggleTarget(target,switchToState);
  469.                         }
  470.                     }
  471.                     else {
  472.                         var table=source.parentNode.parentNode;
  473.                         for (var i=1;i<table.childNodes.length;i++) {
  474.                             target=table.childNodes[i];
  475.                             if(target.style) {
  476.                                 dBug_toggleTarget(target,switchToState);
  477.                             }
  478.                         }
  479.                     }
  480.                 }
  481.             </script>
  482.  
  483.             <style type="text/css">
  484.                 table.dBug_array,table.dBug_object,table.dBug_resource,table.dBug_resourceC,table.dBug_xml
  485.                     { font-family:Verdana, Arial, Helvetica, sans-serif; color:# 000000; font-size:12px; border-spacing:2px; display:table; border-collapse:separate; }
  486.  
  487.                 table.dBug_array td,
  488.                 table.dBug_object td,
  489.                 table.dBug_resource td,
  490.                 table.dBug_resourceC td,
  491.                 table.dBug_xml td
  492.                     { line-height:1.3; padding:3px; vertical-align:top; }
  493.  
  494.                 .dBug_arrayHeader,
  495.                 .dBug_objectHeader,
  496.                 .dBug_resourceHeader,
  497.                 .dBug_resourceCHeader,
  498.                 .dBug_xmlHeader
  499.                     { font-weight:bold; color:# FFFFFF; cursor:pointer; }
  500.  
  501.                 .dBug_arrayKey,
  502.                 .dBug_objectKey,
  503.                 .dBug_xmlKey
  504.                     { cursor:pointer; }
  505.  
  506.                 /* array */
  507.                 table.dBug_array { background-color:# 006600; }
  508.                 table.dBug_array td { background-color:# FFFFFF; }
  509.                 table.dBug_array td.dBug_arrayHeader { background-color:# 009900; }
  510.                 table.dBug_array td.dBug_arrayKey { background-color:# CCFFCC; }
  511.  
  512.                 /* object */
  513.                 table.dBug_object { background-color:# 0000CC; }
  514.                 table.dBug_object td { background-color:# FFFFFF; }
  515.                 table.dBug_object td.dBug_objectHeader { background-color:# 4444CC; }
  516.                 table.dBug_object td.dBug_objectKey { background-color:# CCDDFF; }
  517.  
  518.                 /* resource */
  519.                 table.dBug_resourceC { background-color:# 884488; }
  520.                 table.dBug_resourceC td { background-color:# FFFFFF; }
  521.                 table.dBug_resourceC td.dBug_resourceCHeader { background-color:# AA66AA; }
  522.                 table.dBug_resourceC td.dBug_resourceCKey { background-color:# FFDDFF; }
  523.  
  524.                 /* resource */
  525.                 table.dBug_resource { background-color:# 884488; }
  526.                 table.dBug_resource td { background-color:# FFFFFF; }
  527.                 table.dBug_resource td.dBug_resourceHeader { background-color:# AA66AA; }
  528.                 table.dBug_resource td.dBug_resourceKey { background-color:# FFDDFF; }
  529.  
  530.                 /* xml */
  531.                 table.dBug_xml { background-color:# 888888; }
  532.                 table.dBug_xml td { background-color:# FFFFFF; }
  533.                 table.dBug_xml td.dBug_xmlHeader { background-color:# AAAAAA; }
  534.                 table.dBug_xml td.dBug_xmlKey { background-color:# DDDDDD; }
  535.             </style>
  536. SCRIPTS;
  537.     }
  538.  
  539. }
  540. ?>
  541.  
Tags: php Debugging
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement