ice framework documentation ice doc v1.10.1
Class Ice

Dump

    
namespace Ice;

use ReflectionClass;
use ReflectionObject;
use stdClass;

/**
 * Dumps information about a variable(s)
 *
 * @package     Ice/Dump
 * @category    Helper
 * @author      Ice Team
 * @copyright   (c) 2014-2023 Ice Team
 * @license     http://iceframework.org/license
 *
 * 

 *  $foo = 123;
 *  echo (new \Ice\Dump())->variable($foo, "foo");
 * 
* *

 *  $foo = "string";
 *  $bar = ["key" => "value"];
 *  $baz = new stdClass();
 *  echo (new \Ice\Dump())->vars($foo, $bar, $baz);
 * 
* * Sleet usage: *

 *  {{ dump('str', 1, 2.5, true, null, ['key': 'value']) }}
 * 
*/ class Dump { protected detailed = false { get, set }; protected plain = false { get, set }; protected skip = ["Ice\\Di"] { get, set }; protected methods = []; protected objects = []; protected styles = []; /** * Dump constructor * * @param boolean detailed debug object's private and protected properties * @param mixed styles */ public function __construct(boolean detailed = false, var styles = []) { if typeof styles == "array" { this->setStyles(styles); } elseif typeof styles == "boolean" { let this->plain = styles; } let this->detailed = detailed; } /** * Alias of vars() method * *

     *  echo (new \Ice\Dump())->all($foo, $bar, $baz);
     * 
* * @param mixed variable * @param ... * @return string */ public function all() -> string { return call_user_func_array([this, "vars"], func_get_args()); } /** * Get style for type * * @param string type * @return string */ protected function getStyle(string! type) -> string { var style; if fetch style, this->styles[type] { return style; } else { return "color:gray"; } } /** * Set styles for vars type * Styles: pre, arr, bool, float, int, null, num, obj, other, res, str * * @param array styles * @return array */ public function setStyles(array styles = []) -> array { var defaultStyles; if typeof styles != "array" { throw new Exception("The styles must be an array"); } let defaultStyles = [ "pre": "background-color:#f9f9f9; font-size:11px; padding:10px; border:1px solid #ccc; text-align:left; color:#333", "arr": "color:red", "bool": "color:green", "float": "color:fuchsia", "int": "color:blue", "null": "color:black", "num": "color:navy", "obj": "color:purple", "other": "color:maroon", "res": "color:lime", "str": "color:teal", "line": "highlight-block", "lines": "" ]; let this->styles = array_merge(defaultStyles, styles); return this->styles; } /** * Alias of variable() method * *

     *  echo (new \Ice\Dump())->one($foo, "foo");
     * 
* * @param mixed variable * @param string name * @return string */ public function one(variable, string name = null) -> string { return this->variable(variable, name); } /** * Prepare an HTML string of information about a single variable. * * @param mixed variable * @param string name * @param integer tab * @return string */ protected function output(variable, name = null, tab = 1) -> string { var key, value, output, space, type, attr; let space = " ", output = ""; if name { let output = name . " "; } if typeof variable == "array" { let output .= strtr((this->plain ? "array (:count) (" . PHP_EOL : "array (:count) (" . PHP_EOL), [":style": this->getStyle("arr"), ":count": count(variable)]); for key, value in variable { let output .= str_repeat(space, tab) . strtr((this->plain ? "[:key] => " : "[:key] => "), [":style": this->getStyle("arr"), ":key": key]); if tab == 1 && name != "" && !is_int(key) && name == key { continue; } else { let output .= this->output(value, "", tab + 1) . PHP_EOL; } } return output . str_repeat(space, tab - 1) . ")"; } if typeof variable == "object" { var className, hash; let className = get_class(variable), hash = spl_object_hash(variable), output .= strtr((this->plain ? "object :class" : "object :class"), [":style": this->getStyle("obj"), ":class": className]); if get_parent_class(variable) { let output .= strtr((this->plain ? " extends :parent" : " extends :parent"), [":style": this->getStyle("obj"), ":parent": get_parent_class(variable)]); } let output .= " (" . PHP_EOL; if in_array(className, this->skip) { // Skip debuging let output .= str_repeat(space, tab) . "[skipped]" . PHP_EOL; } elseif in_array(hash, this->objects) { // Recursion let output .= str_repeat(space, tab) . "[already listed]" . PHP_EOL; } elseif !this->detailed { // Debug only public properties for key, value in get_object_vars(variable) { let this->objects[] = hash, output .= str_repeat(space, tab) . strtr((this->plain ? "->:key (:type) = " : "->:key (:type) = "), [":style": this->getStyle("obj"), ":key": key, ":type": "public"]), output .= this->output(value, "", tab + 1) . PHP_EOL; } } else { // Debug all properties var reflect; let reflect = variable instanceof stdClass ? new ReflectionObject(variable) : new ReflectionClass(variable); for attr in reflect->getProperties() { let key = attr->getName(), type = "public"; if attr->isProtected() { attr->setAccessible(true); let type = "protected"; } if attr->isPrivate() { attr->setAccessible(true); let type = "private"; } if attr->isStatic() { let type .= " static"; } let value = attr->getValue(variable); let this->objects[] = hash, output .= str_repeat(space, tab) . strtr((this->plain ? "->:key (:type) = " : "->:key (:type) = "), [":style": this->getStyle("obj"), ":key": key, ":type": type]), output .= this->output(value, "", tab + 1) . PHP_EOL; } } let attr = get_class_methods(variable), output .= str_repeat(space, tab) . strtr((this->plain ? ":class methods: (:count) (" . PHP_EOL : ":class methods: (:count) (" . PHP_EOL), [":style": this->getStyle("obj"), ":class": className, ":count": count(attr)]); if in_array(className, this->methods) { let output .= str_repeat(space, tab) . "[already listed]" . PHP_EOL; } else { for value in attr { if !in_array(className, this->methods) { let this->methods[] = className; } if value == "__construct" { let output .= str_repeat(space, tab + 1) . strtr((this->plain ? "->:method(); [constructor]" . PHP_EOL : "->:method(); [constructor]" . PHP_EOL), [":style": this->getStyle("obj"), ":method": value]); } else { let output .= str_repeat(space, tab + 1) . strtr((this->plain ? "->:method();" . PHP_EOL : "->:method();" . PHP_EOL), [":style": this->getStyle("obj"), ":method": value]); } } let output .= str_repeat(space, tab) . ")" . PHP_EOL; } return output . str_repeat(space, tab - 1) . ")"; } if is_int(variable) { return output . strtr((this->plain ? "integer (:var)" : "integer (:var)"), [":style": this->getStyle("int"), ":var": variable]); } if is_float(variable) { return output . strtr((this->plain ? "float (:var)" : "float (:var)"), [":style": this->getStyle("float"), ":var": variable]); } if is_numeric(variable) { return output . strtr((this->plain ? "numeric string (:length) \":var\"" : "numeric string (:length) \":var\""), [":style": this->getStyle("num"), ":length": strlen(variable), ":var": variable]); } if is_string(variable) { return output . strtr((this->plain ? "string (:length) \":var\"" : "string (:length) \":var\""), [":style": this->getStyle("str"), ":length": strlen(variable), ":var": nl2br(htmlentities(variable, ENT_IGNORE, "utf-8"))]); } if is_bool(variable) { return output . strtr((this->plain ? "boolean (:var)" : "boolean (:var)"), [":style": this->getStyle("bool"), ":var": (variable ? "true" : "false")]); } if is_null(variable) { return output . strtr((this->plain ? "null" : "null"), [":style": this->getStyle("null")]); } return output . strtr((this->plain ? "(:var)" : "(:var)"), [":style": this->getStyle("other"), ":var": variable]); } /** * Returns an HTML string of information about a single variable. * *

     *  $foo = 123;
     *  echo (new \Ice\Dump())->variable($foo, "foo");
     * 
* * @param mixed variable * @param string name * @return string */ public function variable(variable, string name = null) -> string { return strtr((this->plain ? ":output" : "
:output
"), [":style": this->getStyle("pre"), ":output": this->output(variable, name)]); } /** * Returns an HTML string of debugging information about any number of * variables, each wrapped in a "pre" tag. * *

     *  $foo = "string";
     *  $bar = ["key" => "value"];
     *  $baz = new stdClass();
     *  echo (new \Ice\Dump())->vars($foo, $bar, $baz);
     * 
* * @param mixed variable * @param ... * @return string */ public function vars() -> string { var key, value, output; let output = ""; for key, value in func_get_args() { let output .= this->one(value, "var " . key); } return output; } /** * Returns an HTML string, highlighting a specific line of a file, with some number of lines padded above and below. * * @param string file File to open * @param integer line Line number to highlight * @param integer padding Number of padding lines * @return array Source of file, false if file is unreadable */ public function source(string filename, int line, int padding = 5) -> array|boolean { var file, range, format, lines, row; int i = 0; if empty filename || !is_readable(filename) { // Continuing will cause errors return false; } // Open the file and set the line position let file = fopen(filename, "r"); // Set the reading range let range = [ "start": line - padding, "end": line + padding ]; // Set the zero-padding amount for line numbers let format = "% " . strlen(range["end"]) . "d", lines = [], row = fgets(file); while !feof(file) { if row === false { break; } // Increment the line number let i++; if i > range["end"] { break; } if i >= range["start"] { // Make the row safe for output let row = htmlspecialchars(row, ENT_NOQUOTES, "utf-8"); if i === line { // Apply highlighting to this row let lines[sprintf(format, i)] .= strtr((this->plain ? ":var" : "
:var
"), [":class": this->getStyle("line"), ":var": row]); } else { let lines[sprintf(format, i)] .= strtr((this->plain ? ":var" : "
:var
"), [":class": this->getStyle("lines"), ":var": row]); } } let row = fgets(file); } // Close the file fclose(file); return lines; } }