You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
495 lines
14 KiB
495 lines
14 KiB
<?php
|
|
|
|
/**
|
|
* Dump structured data, i.e., Objects and Arrays, in either plain text or
|
|
* html. This is a class wrapper for a couple of utility routines that I use
|
|
* all the time. It's handier to have them as a class.
|
|
*
|
|
* Its also the class interface for logging functions that I use in developing
|
|
* web enabled applications.
|
|
*
|
|
* @author Dick Munroe <munroe@csworks.com>
|
|
* @copyright copyright @ by Dick Munroe, 2004
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
|
* @package StructuredDataDumper
|
|
* @version 1.0.4
|
|
*/
|
|
|
|
//
|
|
// Edit History:
|
|
//
|
|
// Dick Munroe munroe@cworks.com 04-Dec-2004
|
|
// Initial version created.
|
|
//
|
|
// Dick Munroe munroe@csworks.com 08-Dec-2004
|
|
// Translate < to < for html output.
|
|
//
|
|
// Dick Munroe munroe@csworks.com 23-Dec-2004
|
|
// Add interface for writing "stuff". Extend SDD
|
|
// to get things "written".
|
|
//
|
|
// Dick Munroe munroe@csworks.com 25-Dec-2004
|
|
// If a class extends a base class, but doesn't add
|
|
// data members, a warning winds up appearing when
|
|
// printing.
|
|
// Added a memeber to fetch the state of the logging
|
|
// flag.
|
|
//
|
|
// Dick Munroe munroe@csworks.com 11-Mar-2006
|
|
// The test for html flag should have assumed that
|
|
// $this can be defined for objects calling SDD::dump.
|
|
//
|
|
// Dick Munroe (munroe@csworks.com) 22-Mar-2006
|
|
// Add a function to generate "newlines".
|
|
//
|
|
|
|
class SDD
|
|
{
|
|
/**
|
|
* HTML to be generated flag.
|
|
*/
|
|
|
|
var $m_htmlFlag ;
|
|
|
|
/**
|
|
* logging flag.
|
|
*/
|
|
|
|
var $m_logging = false ;
|
|
|
|
/**
|
|
* In memory log file.
|
|
*/
|
|
|
|
var $m_log = array() ;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @access public
|
|
* @param boolean $theHTMLFlag [optional] True if HTML is to be generated.
|
|
* If omitted, $_SERVER is used to "guess" the state of
|
|
* the HTML flag. Be default, HTML is generated when
|
|
* accessed by a web server.
|
|
* @param boolean $theLoggingFlag [optional] the state of logging for
|
|
* this object. By default, logging is off.
|
|
*/
|
|
|
|
function SDD($theHtmlFlag=null, $theLoggingFlag=false)
|
|
{
|
|
if ($theHtmlFlag === null)
|
|
{
|
|
$theHtmlFlag = (!empty($_SERVER['DOCUMENT_ROOT'])) ;
|
|
}
|
|
|
|
$this->m_htmlFlag = $theHtmlFlag ;
|
|
$this->m_logging = $theLoggingFlag ;
|
|
}
|
|
|
|
/**
|
|
* Close the log file.
|
|
*
|
|
* @access public
|
|
* @abstract
|
|
*/
|
|
|
|
function close()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Dump a structured variable.
|
|
*
|
|
* @static
|
|
* @param mixed $theVariable the variable to be dumped.
|
|
* @param boolean $theHtmlFlag [optional] true if HTML is to be generated,
|
|
* false if plain text is to be generated, null (default) if
|
|
* dump is to guess which to display.
|
|
* @return string The data to be displayed.
|
|
* @link http://www.php.net/manual/en/reserved.variables.php#reserved.variables.server Uses $_SERVER
|
|
*/
|
|
|
|
function dump(&$theVariable, $theHtmlFlag=null)
|
|
{
|
|
if ($theHtmlFlag === null)
|
|
{
|
|
if (empty($this))
|
|
{
|
|
$theHtmlFlag = (!empty($_SERVER['DOCUMENT_ROOT'])) ;
|
|
}
|
|
else
|
|
{
|
|
if (is_subclass_of($this, "sdd"))
|
|
{
|
|
$theHtmlFlag = $this->m_htmlFlag ;
|
|
}
|
|
else
|
|
{
|
|
$theHtmlFlag = (!empty($_SERVER['DOCUMENT_ROOT'])) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (gettype($theVariable))
|
|
{
|
|
case 'array':
|
|
{
|
|
return SDD::dArray($theVariable, $theHtmlFlag) ;
|
|
}
|
|
|
|
case 'object':
|
|
{
|
|
return SDD::dObject($theVariable, $theHtmlFlag) ;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return SDD::scalar($theVariable, $theHtmlFlag) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dump the contents of an array.
|
|
*
|
|
* @param array $theArray the array whose contents are to be displayed.
|
|
* @param boolean $theHTMLFlag True if an HTML table is to be generated,
|
|
* false otherwise.
|
|
* @param string $theIndent [optional] Used by SDD::dArray during recursion
|
|
* to get indenting right.
|
|
* @return string The display form of the array.
|
|
*/
|
|
|
|
function dArray(&$theArray, $theHTMLFlag, $theIndent = "")
|
|
{
|
|
$theOutput = array() ;
|
|
|
|
foreach($theArray as $theIndex => $theValue)
|
|
{
|
|
if (is_array($theValue))
|
|
{
|
|
$theString = SDD::dArray($theValue, $theHTMLFlag, $theIndent . " ") ;
|
|
$theOutput[$theIndex] = substr($theString, 0, strlen($theString) - 1) ;
|
|
}
|
|
else if (is_object($theValue))
|
|
{
|
|
$theOutput[$theIndex] = SDD::dObject($theValue, $theHTMLFlag) ;
|
|
}
|
|
else
|
|
{
|
|
$theOutput[$theIndex] = ($theHTMLFlag ?
|
|
preg_replace('|<|s', '<', var_export($theValue, true)) :
|
|
var_export($theValue, true)) ;
|
|
}
|
|
}
|
|
|
|
if ($theHTMLFlag)
|
|
{
|
|
$theString = "<table border=1>\n" ;
|
|
$theString .= "<tr><td align=left>Array (</td></tr>\n" ;
|
|
|
|
foreach ($theOutput as $theIndex => $theVariableOutput)
|
|
{
|
|
$theString .= "<tr>\n<td align=right>$theIndex = ></td><td align=left>\n$theVariableOutput\n</td>\n</tr>\n" ;
|
|
}
|
|
|
|
$theString .= "<tr><td align=left>)</td></tr>\n" ;
|
|
$theString .= "</table>\n" ;
|
|
}
|
|
else
|
|
{
|
|
$theString = "Array\n$theIndent(\n" ;
|
|
|
|
foreach ($theOutput as $theIndex => $theVariableOutput)
|
|
{
|
|
$theString .= "$theIndent [$theIndex] => " . $theVariableOutput . "\n" ;
|
|
}
|
|
|
|
$theString .= "$theIndent)\n" ;
|
|
}
|
|
|
|
return $theString ;
|
|
}
|
|
|
|
/**
|
|
* Dump the contents of an object.
|
|
*
|
|
* Provide a structured display of an object and all the
|
|
* classes from which it was derived. The contents of
|
|
* the object is displayed from most derived to the base
|
|
* class, in order.
|
|
*
|
|
* @param object $theObject the object to be dumped.
|
|
* @param boolean $theHTMLFlag true if HTML is to be generated.
|
|
* @return string the display form of the object.
|
|
*/
|
|
|
|
function dObject(&$theObject, $theHTMLFlag)
|
|
{
|
|
$theObjectVars = get_object_vars($theObject) ;
|
|
|
|
//
|
|
// Get the inheritance tree starting with the object and going
|
|
// through all the parent classes from there.
|
|
//
|
|
|
|
$theClass = get_class($theObject) ;
|
|
|
|
$theClasses[] = $theClass ;
|
|
|
|
while ($theClass = get_parent_class($theClass))
|
|
{
|
|
$theClasses[] = $theClass ;
|
|
}
|
|
|
|
//
|
|
// Get all the class variables for each class in the inheritance
|
|
// tree. There will be some duplication, but we'll sort that out
|
|
// in the output process.
|
|
//
|
|
|
|
foreach($theClasses as $theClass)
|
|
{
|
|
$theClassVars[$theClass] = get_class_vars($theClass) ;
|
|
}
|
|
|
|
//
|
|
// Put the inheritance tree from base class to most derived order
|
|
// (this is how we get rid of duplication of the variable names)
|
|
// Go through the object variables starting with the base class,
|
|
// capture the output and delete the variable from the object
|
|
// variables.
|
|
//
|
|
|
|
$theClasses = array_reverse($theClasses) ;
|
|
|
|
$theOutput = array() ;
|
|
|
|
foreach ($theClasses as $theClass)
|
|
{
|
|
$theOutput[$theClass] = array() ;
|
|
|
|
foreach ($theClassVars[$theClass] as $theVariable => $value)
|
|
{
|
|
if (array_key_exists($theVariable, $theObjectVars))
|
|
{
|
|
if (is_array($theObjectVars[$theVariable]))
|
|
{
|
|
$theOutput[$theClass][] = $theVariable . " = " . SDD::dArray($theObjectVars[$theVariable], $theHTMLFlag) ;
|
|
}
|
|
else if (is_object($theObjectVars[$theVariable]))
|
|
{
|
|
$theOutput[$theClass][] = $theVariable . " = " . SDD::dObject($theObjectVars[$theVariable], $theHTMLFlag) ;
|
|
}
|
|
else
|
|
{
|
|
$theOutput[$theClass][] =
|
|
$theVariable . " = " .
|
|
($theHTMLFlag ?
|
|
preg_replace('|<|s', '<', var_export($theObjectVars[$theVariable], true)) :
|
|
var_export($theObjectVars[$theVariable], true)) ;
|
|
}
|
|
|
|
unset($theObjectVars[$theVariable]) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Put the classes back in most derived order for generating printable
|
|
// output.
|
|
//
|
|
|
|
$theClasses = array_reverse($theClasses) ;
|
|
|
|
if ($theHTMLFlag)
|
|
{
|
|
$theString = "<table>\n<thead>\n" ;
|
|
|
|
foreach ($theClasses as $theClass)
|
|
{
|
|
$theString .= "<th>\n$theClass\n</th>\n" ;
|
|
}
|
|
|
|
$theString .= "</thead>\n<tr valign=top>\n" ;
|
|
|
|
foreach ($theClasses as $theClass)
|
|
{
|
|
$theString .= "<td>\n<table border=1>\n" ;
|
|
|
|
foreach ($theOutput[$theClass] as $theVariableOutput)
|
|
{
|
|
$theString .= "<tr>\n<td>\n$theVariableOutput\n</td>\n</tr>\n" ;
|
|
}
|
|
|
|
$theString .= "</table>\n</td>\n" ;
|
|
}
|
|
|
|
$theString .= "</tr>\n</table>\n" ;
|
|
}
|
|
else
|
|
{
|
|
|
|
$classIndent = "" ;
|
|
|
|
$classDataIndent = " " ;
|
|
|
|
$theString = "" ;
|
|
|
|
foreach ($theClasses as $theClass)
|
|
{
|
|
$theString .= "{$classIndent}class $theClass\n\n" ;
|
|
|
|
foreach ($theOutput[$theClass] as $theVariableOutput)
|
|
{
|
|
$theString .= "$classDataIndent$theVariableOutput\n" ;
|
|
}
|
|
|
|
$theString .= "\n" ;
|
|
|
|
$classIndent .= " " ;
|
|
|
|
$classDataIndent .= " " ;
|
|
}
|
|
}
|
|
|
|
return $theString ;
|
|
}
|
|
|
|
/**
|
|
* Write a debugging value to a log file.
|
|
*
|
|
* @access public
|
|
* @abstract
|
|
* @param mixed Data to be logged.
|
|
* @param string $theHeader [optional] string to be emitted prior to
|
|
* logging the data. By default it is a date/time
|
|
* stamp.
|
|
*/
|
|
|
|
function log(&$theData, $theHeader=null)
|
|
{
|
|
$theHeader = date('[Y-m-d H:i:s]: ') . $theHeader ;
|
|
|
|
if ($this->m_logging)
|
|
{
|
|
if ($this->m_htmlFlag)
|
|
{
|
|
$xxx = $this->dump($theData) ;
|
|
if (substr($xxx, 0, 5) == '<pre>')
|
|
{
|
|
$xxx = '<pre>' . $theHeader . substr($xxx, 5) ;
|
|
}
|
|
else
|
|
{
|
|
$xxx = $theHeader . $xxx ;
|
|
}
|
|
|
|
$this->writeLog($xxx) ;
|
|
}
|
|
else
|
|
{
|
|
$xxx = $theHeader . $this->dump($theData) ;
|
|
$this->writeLog($xxx) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @desc Generate context specific new line equivalents.
|
|
* @param integer [optional] the number of newlines.
|
|
* @param boolean [optional] true if generating html newlines.
|
|
* @return string newlines.
|
|
* @access public
|
|
*/
|
|
|
|
function newline($theCount=1, $theHtmlFlag=null)
|
|
{
|
|
if ($theHtmlFlag === null)
|
|
{
|
|
if (empty($this))
|
|
{
|
|
$theHtmlFlag = (!empty($_SERVER['DOCUMENT_ROOT'])) ;
|
|
}
|
|
else
|
|
{
|
|
if (is_subclass_of($this, "sdd"))
|
|
{
|
|
$theHtmlFlag = $this->m_htmlFlag ;
|
|
}
|
|
else
|
|
{
|
|
$theHtmlFlag = (!empty($_SERVER['DOCUMENT_ROOT'])) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($theHtmlFlag)
|
|
{
|
|
return str_repeat("<br />", max($theCount, 0)) . "\n" ;
|
|
}
|
|
else
|
|
{
|
|
return str_repeat("\n", max($theCount, 0)) ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dump any scalar value
|
|
*
|
|
* @param mixed $theVariable the variable to be dumped.
|
|
* @param boolean $theHtmlFlag true if html is to be generated.
|
|
*/
|
|
|
|
function scalar(&$theVariable, $theHtmlFlag)
|
|
{
|
|
if ($theHtmlFlag)
|
|
{
|
|
return "<pre>" . preg_replace('|<|s', '<', var_export($theVariable, true)) . "</pre>" ;
|
|
}
|
|
else
|
|
{
|
|
return var_export($theVariable, true) ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write data to the log file.
|
|
*
|
|
* @access public
|
|
* @abstract
|
|
* @parameter string $theData [by reference] the data to be written
|
|
* into the log file.
|
|
* @return integer the number of bytes written into the log file.
|
|
*/
|
|
|
|
function writeLog(&$theData)
|
|
{
|
|
return strlen($this->m_log[] = $theData) ;
|
|
}
|
|
|
|
/**
|
|
* Return the state of the logging flag.
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
|
|
function getLogging()
|
|
{
|
|
return $this->m_logging ;
|
|
}
|
|
|
|
/**
|
|
* Set the state of the logging flag.
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
|
|
function setLogging($theLogging=false)
|
|
{
|
|
$this->m_logging = $theLogging ;
|
|
}
|
|
}
|
|
?>
|