<?php
// $Id$
/**
* @file
* Devel add-on module that outputs a themer friendly alternative to dprint_r, dpr, and dvm.
*
* This module generates a prettier and friendlies output for the dprint_r() function that
* allows themers and developers to cut-n-paste the displayed variable references.
* Long strings of text and (x)html are also suppressed to insure that the output is read-able.
* Finally, themers and developers can control the number of nested arrays and objects to
* be displayed and then toggle open and close the arrays or objects they wish to examine.
*
* @code
* // Basic examples
* dprx($variables);
* // This generate an output that initially display 3 levels of data.
* dprx($variables, 3);
* // This is the recommended format for the value parameter.
* // By passing in the variable name ($variables) into dprint_rx()
* // the output will contain the full PHP string for every variable.
* dprx(array('$variables' => $variables));@endcode
*
* Learn more about the dprint_rx() function and view an example at my website
* @link http://thebigbluehouse.com/printr-not-pretty http://thebigbluehouse.com/printr-not-pretty @endlink.
*
* Notes
* - Loosely based on contemplates contemplate_array_variables() recursion.
* - Style and color scheme is based on the output from ColdFusion's <CFDUMP> tag.
*
* Related/Similar modules
* - @link http://krumo.kaloyan.info/ Krumo @endlink
*/
/**
* Print a variable in a friendly and usable format to the page.
*
* @param $value
* Value to be displayed
* @param $expand
* Number of levels to be initially expanded
* @param $return
* TRUE will return the output and FALSE will print the output
*/
function dprint_rx($value, $expand = 1, $return = FALSE) {
// This recursion limit could be set from a settings page but 9 seems like a reasonable level.
$recursion_limit = 9;
// Get type
$type = gettype($value);
// Cast object as array
$value = (array)$value;
$output = '';
if ($type == 'array' || $type == 'object') { // Recurse
// Get path
$base_path = base_path();
$path = drupal_get_path('module', 'devel_helper');
// Load css and js the drupal way but if the page is not fully rendered the css and js is added below.
drupal_add_css($path .'/dprx.css', 'module');
drupal_add_js($path .'/dprx.js', 'module');
// CSS and JS will be directly embedded to insure they are loaded even if the output is not rendered inside a drupal template.
// This code would only be loaded when someone calls dprint_rx(); and then exit();
// or they call dprx() within the templatepage.tpl.php which has already loaded the css and js.
// NOTE: This approach is not valid xhtml but it allows the needed css and js to remain in external files.
// Check for jQuery and Drupal
$output .= '<script type="text/javascript">';
$output .= 'if(!window.jQuery){document.write(\'<\' + \'script type="text/javascript" src="'. $base_path .'misc/jquery.js"></\' + \'script>\');}';
$output .= 'if(!window.Drupal){document.write(\'<\' + \'script type="text/javascript" src="'. $base_path .'misc/drupal.js"></\' + \'script>\');}';
$output .= '</script>';
// Check for initDevelHelper behavior. If it is not loaded assume the css is missing
$output .= '<script type="text/javascript">';
$output .= 'if(!Drupal.behaviors.initDevelHelper){';
$output .= 'document.write(\'<link type="text/css" rel="stylesheet" media="all" href="'. $base_path . $path .'/dprx.css" />\');';
$output .= 'document.write(\'<\' + \'script type="text/javascript" src="'. $base_path . $path .'/dprx.js"></\' + \'script>\');';
$output .= '}</script>';
// Look for a variable names, beginning with $, in the value's keys then output them separately.
$keys = array_keys($value);
foreach ($keys as $arr_key) {
if (strpos($arr_key, '$') === 0) {
$output .= '<div class="dprx">';
$output .= _dprint_rx_recurse($value[$arr_key], $arr_key, $expand, 0, $recursion_limit);
$output .= '</div>';
// Remove the value
unset($value[$arr_key]);
}
}
// If $value still contains items then output the data.
if (count($value)) {
$output .= '<div class="dprx">';
$output .= _dprint_rx_recurse($value, FALSE, $expand, 0, $recursion_limit);
$output .= '</div>';
}
}
else { // A single item
$output .= '<pre class="dprx">'. var_export($value, TRUE) .'</pre>';
}
if ($return) {
return $output;
}
else {
print($output);
}
}
/**
* Shortcut alias for dprint_rx().
*/
function dprx($value, $expand = 1) {
dprint_rx($value, $expand);
}
/**
* Print a variable in a friendly and usable format to the 'message' area of the page. Uses drupal_set_message()
*/
function dvmx($value, $expand = 1) {
drupal_set_message( dprint_rx($value, $expand, TRUE) );
}
/**
* Recurses a variable to generate a friendly and usable format to be displayed by dprint_rx(), dprx(), and dvmx().
*/
function _dprint_rx_recurse($value, $key, $expand, $depth, $recursion_limit) {
// Check recursion limit
if ($depth >= $recursion_limit) {
return '';
}
// Get type
$type = gettype($value);
// Cast object to array
$value = (array)$value;
// Set css class dprx-{type} and whether expanded closed.
$output .= '<div class="dprx-'. $type . (($depth >= $expand)?' dprx-closed':'') .'">'; // start .dprx-{type}-item
// Array and object title
$output .= '<div class="dprx-title dprx-'. $type .'-title">'; // start .dprx-{type}-title
$output .= ($key !== '' && $key !== FALSE) ? $key .' = ' : '';
$output .= (($type == 'array') ? 'array()':'new stdClass()') .';';
$output .= '</div>';
$output .= '<div class="dprx-'. $type .'-value">';
// Loop the arrays and (array)objects.
foreach ($value as $arr_key => $arr_value) {
// Format $key with object or array syntax
if ($key) {
if ($type == 'object') {
$arr_key = $key .'->'. $arr_key;
}
else {
$arr_key = $key . ((is_int($arr_key)) ? '['. $arr_key .']':'[\''. $arr_key .'\']');
}
}
if (is_array($arr_value) || is_object($arr_value)) {
// Recurse through objects and arrays
$output .= _dprint_rx_recurse($arr_value, $arr_key, $expand, $depth+1, $recursion_limit);
}
else {
// Display other data types
$arr_type = gettype($arr_value);
$output .= "<div>";
if ($arr_type == 'string' && ($len = drupal_strlen($arr_value)) > 40) {
$output .= $arr_key .' <span>=</span> <a title="'. htmlspecialchars( print_r($arr_value, TRUE) ) .'">{string:'. $len .'}</a>';
}
else if ($arr_type == 'boolean') {
$output .= $arr_key .'<span> = '. (($arr_value ? 'TRUE' : 'FALSE')) .';</span>';
}
else {
$output .= $arr_key .'<span> = '. var_export($arr_value, TRUE) .';</span>';
}
$output .= "</div>";
}
}
$output .= '</div>'; // close .dprx-{type}-value
$output .= '</div>'; // close .dprx-{type}-item
return $output;
}