Debug.php (12353B)
1 <?php 2 3 namespace Finwo\Debug; 4 5 class Debug 6 { 7 8 9 public static $dump_max_depth = 8; 10 public static $dump_max_length = 48; 11 public static $output = null; 12 13 /** 14 * Prints data & overrules all output after the first call. 15 * 16 * Arguments: see sprintf documentation 17 */ 18 static function printf() 19 { 20 21 // Sorry folks, this only works in development mode 22 if (!isset($_ENV['IS_DEVEL']) || !$_ENV['IS_DEVEL']) { 23 return; 24 } 25 26 if (isset($_SERVER['argc'])) { 27 // Command line 28 call_user_func_array('printf', func_get_args()); 29 } else { 30 // Probably web instance 31 32 // Init output overruling 33 if (is_null(self::$output)) { 34 self::$output = ''; 35 ob_start(function ($buffer) { 36 header("Content-Type: text/html"); 37 38 return self::$output; 39 }); 40 } 41 42 self::$output .= call_user_func_array('sprintf', func_get_args()); 43 } 44 } 45 46 /** 47 * @param array $data 48 * @param boolean $html 49 */ 50 static function consoleTable($data, $html = null) 51 { 52 $html = is_null($html) ? !isset($_SERVER['argc']) : !!$html; 53 54 if ($html) { 55 self::printf("<pre>"); 56 } 57 $edges = array( 58 "top-left" => "┌─", 59 "top" => "─┬─", 60 "top-right" => "─┐", 61 "right" => "─┤", 62 "bottom-right" => "─┘", 63 "bottom" => "─┴─", 64 "bottom-left" => "└─", 65 "left" => "├─", 66 "horizontal" => "─", 67 "vertical" => " │ ", 68 "middle" => "─┼─", 69 ); 70 71 $column = array(); 72 73 // Fetch columns & their max length 74 foreach ($data as &$row) { 75 foreach ($row as $key => &$value) { 76 if (!isset($column[$key])) $column[$key] = max(4,strlen($key)); 77 if (is_array($value)) $value = implode(',',array_values($value)); 78 $column[$key] = max($column[$key], strlen($value)); 79 } 80 } 81 82 // Print header 83 self::printf($edges['top-left']); 84 self::printf(implode($edges['top'], array_map(function($length) use ($edges) { 85 return str_repeat($edges['horizontal'], $length); 86 },$column))); 87 self::printf($edges['top-right']); 88 self::printf("\n"); 89 self::printf(ltrim($edges['vertical']) . implode($edges['vertical'],array_map(function($length, $key) use ($edges) { 90 return $key . str_repeat(' ', $length-strlen($key)); 91 }, $column, array_keys($column))) . rtrim($edges['vertical'])); 92 self::printf("\n"); 93 94 // Print rows 95 foreach ($data as $row) { 96 // Seperator 97 self::printf($edges['left']); 98 self::printf(implode($edges['middle'], array_map(function($length) use ($edges) { 99 return str_repeat($edges['horizontal'], $length); 100 },$column))); 101 self::printf($edges['right']); 102 self::printf("\n"); 103 104 // Data.php 105 self::printf(ltrim($edges['vertical'])); 106 self::printf(implode($edges['vertical'], array_map(function($length, $key) use ($row) { 107 $data = isset($row[$key]) ? $row[$key] : 'NULL'; 108 if (is_numeric($data)) { 109 return str_repeat(' ', $length-strlen($data)) . $data; 110 } else { 111 return $data . str_repeat(' ', $length-strlen($data)); 112 } 113 },$column,array_keys($column)))); 114 self::printf(rtrim($edges['vertical'])); 115 self::printf("\n"); 116 } 117 118 // Closing 119 self::printf($edges['bottom-left']); 120 self::printf(implode($edges['bottom'], array_map(function($length) use ($edges) { 121 return str_repeat($edges['horizontal'], $length); 122 },$column))); 123 self::printf($edges['bottom-right']); 124 self::printf("\n"); 125 126 if ($html) { 127 self::printf("</pre>"); 128 } 129 } 130 131 /** 132 * Displays a semi-readable version of a variable. 133 * 134 * @param $input 135 * @param bool $singleline 136 * @param string $indent 137 */ 138 static function dump($input, $singleline = true, $indent = '') 139 { 140 $html = !isset($_SERVER['argc']); 141 142 $colors = array( 143 'indent' => '#CCC', 144 'string' => array( 145 'sys' => '#000', 146 'length' => '#88F', 147 'value' => '#D00', 148 ), 149 'integer' => array( 'value' => '#880' ), 150 'float' => array( 'value' => '#D44' ), 151 'double' => array( 'value' => '#D44' ), 152 'boolean' => array( 'value' => '#D0D' ) 153 ); 154 155 $t = array( 156 "fg" => array( 157 "black" => "\e[30m", 158 "red" => "\e[31m", 159 "green" => "\e[32m", 160 "yellow" => "\e[33m", 161 "blue" => "\e[34m", 162 "magenta" => "\e[35m", 163 "cyan" => "\e[36m", 164 "white" => "\e[37m", 165 "default" => "\e[39m", 166 ), 167 "bg" => array( 168 "black" => "\e[40m", 169 "red" => "\e[41m", 170 "green" => "\e[42m", 171 "yellow" => "\e[43m", 172 "blue" => "\e[44m", 173 "magenta" => "\e[45m", 174 "cyan" => "\e[46m", 175 "white" => "\e[47m", 176 "default" => "\e[49m", 177 ), 178 ); 179 180 $template = array( 181 "header" => $html ? '<div style="font-size:12px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;'.(($singleline)?('white-space:nowrap;'):('')).'">' : $t['bg']['default'].$t['fg']['default'], 182 "footer" => $html ? '</div><br />' : $t['bg']['default'].$t['fg']['default']."\n", 183 "type" => $html ? '<b>%s</b>' : $t['fg']['red'].'%s'.$t['fg']['default'], 184 "class" => $html ? ' <i>%s</i>' : $t['fg']['blue'].' %s'.$t['fg']['default'], 185 "count" => ' (%s)', 186 "linebreak" => $html ? "<br />\n" : "\n", 187 "too_deep" => ' ...', 188 "too_long" => $html ? '<i>(%s more values)</i>' : '(%s more values)', 189 "key" => $html ? sprintf('[%%s] <div style="display:inline;color:%s;">_%%s</div> => ', $colors['indent']) : '[%s] _%s => ', 190 "branch" => array( 191 "default" => $html ? '<div style="display:inline;color:%s;"> ├─ </div>' : ' ├─ ', 192 "last" => $html ? '<div style="display:inline;color:%s;"> └─ </div>' : ' └─ ', 193 ), 194 "indent" => array( 195 "default" => $html ? '<div style="display:inline;color:%s;"> │ </div>' : ' │ ', 196 "last" => $html ? '<div style="display:inline;color:%s;"> </div>' : ' ', 197 ), 198 "chars" => array( 199 "space" => $html ? ' ' : ' ', 200 "tab" => $html ? ' ' : ' ', 201 "\r\n" => $singleline ? ( $html ? sprintf('"<b style=\'color:%s;\'>↵</b>"',$colors['string']['sys']) : "\\r\\n" ) : ( $html ? "<br />\n" : "\n" ), 202 "\r" => $singleline ? ( $html ? sprintf('"<b style=\'color:%s;\'>↵</b>"',$colors['string']['sys']) : "\\r" ) : ( $html ? "<br />\n" : "\n" ), 203 "\n" => $singleline ? ( $html ? sprintf('"<b style=\'color:%s;\'>↵</b>"',$colors['string']['sys']) : "\\n" ) : ( $html ? "<br />\n" : "\n" ), 204 ), 205 "string_length" => array( 206 "start" => $html ? sprintf(" <p style=\"display:inline;color:%s;\">",$colors['string']['length']) : ' '.$t['fg']['yellow'], 207 "value" => '%d', 208 "end" => $html ? '</p>' : $t['fg']['default'] 209 ), 210 "string_value" => array( 211 "start" => $html ? sprintf(' <p style="display:inline;color:%s;">',$colors['string']['value']) : ' '.$t['fg']['green'], 212 "value" => '%s', 213 "end" => $html ? '</p>' : $t['fg']['default'], 214 ), 215 "boolean_start" => $html ? sprintf(' <p style="display:inline;color:%s;">',$colors['boolean']['value']) : $t['fg']['cyan'], 216 "boolean_value" => ' %s', 217 "boolean_end" => $html ? '</p>' : $t['fg']['default'], 218 "float" => array( 219 "start" => $html ? ' <p style="display:inline;color:%s;">' : ' '.$t['fg']['magenta'], 220 "value" => '%.3f', 221 "end" => $html ? '</p>' : $t['fg']['default'], 222 ), 223 ); 224 225 $template['double'] = $template['float']; 226 $template['integer'] = $template['float']; 227 $template['integer']['value'] = '%d'; 228 229 // Sorry folks, this only works in development mode 230 if (!isset($_ENV['IS_DEVEL']) || !$_ENV['IS_DEVEL']) { 231 return; 232 } 233 234 if (!strlen($indent)) { 235 self::printf($template['header']); 236 } 237 self::printf($template['type'], $type = gettype($input)); 238 if ($type == 'object') { 239 self::printf($template['class'], get_class($input)); 240 $input = Data::x2array($input, self::$dump_max_depth+1); 241 } 242 243 switch ($type) { 244 case 'object': 245 case 'array': 246 self::printf($template['count'], count($input)); 247 $length = 0; 248 $keys = array_keys($input); 249 $keyLength = Data::maxLength($keys); 250 while(count($keys)) { 251 $key = array_shift($keys); 252 self::printf($template['linebreak']); 253 self::printf("%s%s", $indent, sprintf($template['branch'][count($keys)?'default':'last'], $colors['indent'])); 254 self::printf($template['key'], $key, str_repeat('_', $keyLength-strlen($key))); 255 256 if ((++$length) > self::$dump_max_length) { 257 self::printf($template['too_long'], $length - self::$dump_max_length); 258 break; 259 } 260 261 self::dump($input[$key], $singleline, $indent . str_replace('%s',$colors['indent'],$template['indent'][count($keys)?'default':'last']) ); 262 } 263 break; 264 case 'string': 265 $input = $html ? htmlspecialchars($input, ENT_QUOTES) : $input; 266 $input = str_replace(" ", $template['chars']['space'], $input); 267 $input = str_replace("\t", $template['chars']['tab'], $input); 268 $input = str_replace("\r\n", $template['chars']["\r\n"], $input); 269 $input = str_replace("\r", $template['chars']["\r"], $input); 270 $input = str_replace("\n", $template['chars']["\n"], $input); 271 272 self::printf($template['string_length']['start']); 273 self::printf($template['string_length']['value'], strlen($input)); 274 self::printf($template['string_length']['end']); 275 276 self::printf($template['string_value']['start']); 277 self::printf($template['string_value']['value'], $input); 278 self::printf($template['string_value']['end']); 279 280 break; 281 case 'boolean': 282 self::printf($template['boolean_start']); 283 self::printf($template['boolean_value'], $input ? 'true' : 'false'); 284 self::printf($template['boolean_end']); 285 break; 286 case 'integer': 287 case 'float': 288 case 'double': 289 self::printf($template[$type]['start'], $colors[$type]['value']); 290 self::printf($template[$type]['value'], $input); 291 self::printf($template[$type]['end']); 292 break; 293 } 294 if (!strlen($indent)) { 295 self::printf($template['footer']); 296 } 297 } 298 }