Advertisement
justin_hanekom

dBug.php

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