Modules

Kohana_Debug

This class is a transparent base class for Debug and should not be accessed directly.

Contains debugging and dumping tools.

package
Kohana
category
Base
author
Kohana Team
copyright
© 2008-2014 Kohana Team
license
http://kohanaframework.org/license

Class declared in SYSPATH/classes/Kohana/Debug.php on line 11.

Constants

  • None

Properties

  • None

Methods

public static dump( mixed $value [, integer $length = integer 128 , integer $level_recursion = integer 10 ] ) (defined in Kohana_Debug)

Returns an HTML string of information about a single variable.

Borrows heavily on concepts from the Debug class of Nette.

Parameters

  • mixed $value required - Variable to dump
  • integer $length = integer 128 - Maximum length of strings
  • integer $level_recursion = integer 10 - Recursion limit

Return Values

  • string

Source Code

public static function dump($value, $length = 128, $level_recursion = 10)
{
    return Debug::_dump($value, $length, $level_recursion);
}

public static path( string $file ) (defined in Kohana_Debug)

Removes application, system, modpath, or docroot from a filename, replacing them with the plain text equivalents. Useful for debugging when you want to display a shorter path.

// Displays SYSPATH/classes/kohana.php
echo Debug::path(Kohana::find_file('classes', 'kohana'));

Parameters

  • string $file required - Path to debug

Return Values

  • string

Source Code

public static function path($file)
{
    if (strpos($file, APPPATH) === 0)
    {
        $file = 'APPPATH'.DIRECTORY_SEPARATOR.substr($file, strlen(APPPATH));
    }
    elseif (strpos($file, SYSPATH) === 0)
    {
        $file = 'SYSPATH'.DIRECTORY_SEPARATOR.substr($file, strlen(SYSPATH));
    }
    elseif (strpos($file, MODPATH) === 0)
    {
        $file = 'MODPATH'.DIRECTORY_SEPARATOR.substr($file, strlen(MODPATH));
    }
    elseif (strpos($file, DOCROOT) === 0)
    {
        $file = 'DOCROOT'.DIRECTORY_SEPARATOR.substr($file, strlen(DOCROOT));
    }
 
    return $file;
}

public static source( string $file , integer $line_number [, integer $padding = integer 5 ] ) (defined in Kohana_Debug)

Returns an HTML string, highlighting a specific line of a file, with some number of lines padded above and below.

// Highlights the current line of the current file
echo Debug::source(__FILE__, __LINE__);

Parameters

  • string $file required - File to open
  • integer $line_number required - Line number to highlight
  • integer $padding = integer 5 - Number of padding lines

Return Values

  • string - Source of file
  • FALSE - File is unreadable

Source Code

public static function source($file, $line_number, $padding = 5)
{
    if ( ! $file OR ! is_readable($file))
    {
        // Continuing will cause errors
        return FALSE;
    }
 
    // Open the file and set the line position
    $file = fopen($file, 'r');
    $line = 0;
 
    // Set the reading range
    $range = array('start' => $line_number - $padding, 'end' => $line_number + $padding);
 
    // Set the zero-padding amount for line numbers
    $format = '% '.strlen($range['end']).'d';
 
    $source = '';
    while (($row = fgets($file)) !== FALSE)
    {
        // Increment the line number
        if (++$line > $range['end'])
            break;
 
        if ($line >= $range['start'])
        {
            // Make the row safe for output
            $row = htmlspecialchars($row, ENT_NOQUOTES, Kohana::$charset);
 
            // Trim whitespace and sanitize the row
            $row = '<span class="number">'.sprintf($format, $line).'</span> '.$row;
 
            if ($line === $line_number)
            {
                // Apply highlighting to this row
                $row = '<span class="line highlight">'.$row.'</span>';
            }
            else
            {
                $row = '<span class="line">'.$row.'</span>';
            }
 
            // Add to the captured source
            $source .= $row;
        }
    }
 
    // Close the file
    fclose($file);
 
    return '<pre class="source"><code>'.$source.'</code></pre>';
}

public static trace( [ array $trace = NULL ] ) (defined in Kohana_Debug)

Returns an array of HTML strings that represent each step in the backtrace.

// Displays the entire current backtrace
echo implode('<br/>', Debug::trace());

Parameters

  • array $trace = NULL - $trace

Return Values

  • string

Source Code

public static function trace(array $trace = NULL)
{
    if ($trace === NULL)
    {
        // Start a new trace
        $trace = debug_backtrace();
    }
 
    // Non-standard function calls
    $statements = array('include', 'include_once', 'require', 'require_once');
 
    $output = array();
    foreach ($trace as $step)
    {
        if ( ! isset($step['function']))
        {
            // Invalid trace step
            continue;
        }
 
        if (isset($step['file']) AND isset($step['line']))
        {
            // Include the source of this step
            $source = Debug::source($step['file'], $step['line']);
        }
 
        if (isset($step['file']))
        {
            $file = $step['file'];
 
            if (isset($step['line']))
            {
                $line = $step['line'];
            }
        }
 
        // function()
        $function = $step['function'];
 
        if (in_array($step['function'], $statements))
        {
            if (empty($step['args']))
            {
                // No arguments
                $args = array();
            }
            else
            {
                // Sanitize the file path
                $args = array($step['args'][0]);
            }
        }
        elseif (isset($step['args']))
        {
            if ( ! function_exists($step['function']) OR strpos($step['function'], '{closure}') !== FALSE)
            {
                // Introspection on closures or language constructs in a stack trace is impossible
                $params = NULL;
            }
            else
            {
                if (isset($step['class']))
                {
                    if (method_exists($step['class'], $step['function']))
                    {
                        $reflection = new ReflectionMethod($step['class'], $step['function']);
                    }
                    else
                    {
                        $reflection = new ReflectionMethod($step['class'], '__call');
                    }
                }
                else
                {
                    $reflection = new ReflectionFunction($step['function']);
                }
 
                // Get the function parameters
                $params = $reflection->getParameters();
            }
 
            $args = array();
 
            foreach ($step['args'] as $i => $arg)
            {
                if (isset($params[$i]))
                {
                    // Assign the argument by the parameter name
                    $args[$params[$i]->name] = $arg;
                }
                else
                {
                    // Assign the argument by number
                    $args[$i] = $arg;
                }
            }
        }
 
        if (isset($step['class']))
        {
            // Class->method() or Class::method()
            $function = $step['class'].$step['type'].$step['function'];
        }
 
        $output[] = array(
            'function' => $function,
            'args'     => isset($args)   ? $args : NULL,
            'file'     => isset($file)   ? $file : NULL,
            'line'     => isset($line)   ? $line : NULL,
            'source'   => isset($source) ? $source : NULL,
        );
 
        unset($function, $args, $file, $line, $source);
    }
 
    return $output;
}

public static vars( ) (defined in Kohana_Debug)

Returns an HTML string of debugging information about any number of variables, each wrapped in a "pre" tag:

// Displays the type and value of each variable
echo Debug::vars($foo, $bar, $baz);

Return Values

  • string

Source Code

public static function vars()
{
    if (func_num_args() === 0)
        return;
 
    // Get all passed variables
    $variables = func_get_args();
 
    $output = array();
    foreach ($variables as $var)
    {
        $output[] = Debug::_dump($var, 1024);
    }
 
    return '<pre class="debug">'.implode("\n", $output).'</pre>';
}

protected static _dump( mixed & $var [, integer $length = integer 128 , integer $limit = integer 10 , integer $level = integer 0 ] ) (defined in Kohana_Debug)

Helper for Debug::dump(), handles recursion in arrays and objects.

Parameters

  • byref mixed $var required - Variable to dump
  • integer $length = integer 128 - Maximum length of strings
  • integer $limit = integer 10 - Recursion limit
  • integer $level = integer 0 - Current recursion level (internal usage only!)

Return Values

  • string

Source Code

protected static function _dump( & $var, $length = 128, $limit = 10, $level = 0)
{
    if ($var === NULL)
    {
        return '<small>NULL</small>';
    }
    elseif (is_bool($var))
    {
        return '<small>bool</small> '.($var ? 'TRUE' : 'FALSE');
    }
    elseif (is_float($var))
    {
        return '<small>float</small> '.$var;
    }
    elseif (is_resource($var))
    {
        if (($type = get_resource_type($var)) === 'stream' AND $meta = stream_get_meta_data($var))
        {
            $meta = stream_get_meta_data($var);
 
            if (isset($meta['uri']))
            {
                $file = $meta['uri'];
 
                if (function_exists('stream_is_local'))
                {
                    // Only exists on PHP >= 5.2.4
                    if (stream_is_local($file))
                    {
                        $file = Debug::path($file);
                    }
                }
 
                return '<small>resource</small><span>('.$type.')</span> '.htmlspecialchars($file, ENT_NOQUOTES, Kohana::$charset);
            }
        }
        else
        {
            return '<small>resource</small><span>('.$type.')</span>';
        }
    }
    elseif (is_string($var))
    {
        // Clean invalid multibyte characters. iconv is only invoked
        // if there are non ASCII characters in the string, so this
        // isn't too much of a hit.
        $var = UTF8::clean($var, Kohana::$charset);
 
        if (UTF8::strlen($var) > $length)
        {
            // Encode the truncated string
            $str = htmlspecialchars(UTF8::substr($var, 0, $length), ENT_NOQUOTES, Kohana::$charset).'&nbsp;&hellip;';
        }
        else
        {
            // Encode the string
            $str = htmlspecialchars($var, ENT_NOQUOTES, Kohana::$charset);
        }
 
        return '<small>string</small><span>('.strlen($var).')</span> "'.$str.'"';
    }
    elseif (is_array($var))
    {
        $output = array();
 
        // Indentation for this variable
        $space = str_repeat($s = '    ', $level);
 
        static $marker;
 
        if ($marker === NULL)
        {
            // Make a unique marker - force it to be alphanumeric so that it is always treated as a string array key
            $marker = uniqid("\x00")."x";
        }
 
        if (empty($var))
        {
            // Do nothing
        }
        elseif (isset($var[$marker]))
        {
            $output[] = "(\n$space$s*RECURSION*\n$space)";
        }
        elseif ($level < $limit)
        {
            $output[] = "<span>(";
 
            $var[$marker] = TRUE;
            foreach ($var as $key => & $val)
            {
                if ($key === $marker) continue;
                if ( ! is_int($key))
                {
                    $key = '"'.htmlspecialchars($key, ENT_NOQUOTES, Kohana::$charset).'"';
                }
 
                $output[] = "$space$s$key => ".Debug::_dump($val, $length, $limit, $level + 1);
            }
            unset($var[$marker]);
 
            $output[] = "$space)</span>";
        }
        else
        {
            // Depth too great
            $output[] = "(\n$space$s...\n$space)";
        }
 
        return '<small>array</small><span>('.count($var).')</span> '.implode("\n", $output);
    }
    elseif (is_object($var))
    {
        // Copy the object as an array
        $array = (array) $var;
 
        $output = array();
 
        // Indentation for this variable
        $space = str_repeat($s = '    ', $level);
 
        $hash = spl_object_hash($var);
 
        // Objects that are being dumped
        static $objects = array();
 
        if (empty($var))
        {
            // Do nothing
        }
        elseif (isset($objects[$hash]))
        {
            $output[] = "{\n$space$s*RECURSION*\n$space}";
        }
        elseif ($level < $limit)
        {
            $output[] = "<code>{";
 
            $objects[$hash] = TRUE;
            foreach ($array as $key => & $val)
            {
                if ($key[0] === "\x00")
                {
                    // Determine if the access is protected or protected
                    $access = '<small>'.(($key[1] === '*') ? 'protected' : 'private').'</small>';
 
                    // Remove the access level from the variable name
                    $key = substr($key, strrpos($key, "\x00") + 1);
                }
                else
                {
                    $access = '<small>public</small>';
                }
 
                $output[] = "$space$s$access $key => ".Debug::_dump($val, $length, $limit, $level + 1);
            }
            unset($objects[$hash]);
 
            $output[] = "$space}</code>";
        }
        else
        {
            // Depth too great
            $output[] = "{\n$space$s...\n$space}";
        }
 
        return '<small>object</small> <span>'.get_class($var).'('.count($array).')</span> '.implode("\n", $output);
    }
    else
    {
        return '<small>'.gettype($var).'</small> '.htmlspecialchars(print_r($var, TRUE), ENT_NOQUOTES, Kohana::$charset);
    }
}