Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Bar
  • BlueScreen
  • Debugger
  • Dumper
  • FireLogger
  • Helpers
  • Logger
  • OutputDebugger

Interfaces

  • IBarPanel
  • ILogger
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Tracy (https://tracy.nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Tracy;
  9: 
 10: 
 11: /**
 12:  * Rendering helpers for Debugger.
 13:  */
 14: class Helpers
 15: {
 16: 
 17:     /**
 18:      * Returns HTML link to editor.
 19:      * @return string
 20:      */
 21:     public static function editorLink($file, $line = NULL)
 22:     {
 23:         if ($editor = self::editorUri($file, $line)) {
 24:             $file = strtr($file, '\\', '/');
 25:             if (preg_match('#(^[a-z]:)?/.{1,50}$#i', $file, $m) && strlen($file) > strlen($m[0])) {
 26:                 $file = '...' . $m[0];
 27:             }
 28:             $file = strtr($file, '/', DIRECTORY_SEPARATOR);
 29:             return self::formatHtml('<a href="%" title="%">%<b>%</b>%</a>',
 30:                 $editor,
 31:                 $file . ($line ? ":$line" : ''),
 32:                 rtrim(dirname($file), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
 33:                 basename($file),
 34:                 $line ? ":$line" : ''
 35:             );
 36:         } else {
 37:             return self::formatHtml('<span>%</span>', $file . ($line ? ":$line" : ''));
 38:         }
 39:     }
 40: 
 41: 
 42:     /**
 43:      * Returns link to editor.
 44:      * @return string
 45:      */
 46:     public static function editorUri($file, $line = NULL)
 47:     {
 48:         if (Debugger::$editor && $file && is_file($file)) {
 49:             return strtr(Debugger::$editor, array('%file' => rawurlencode($file), '%line' => $line ? (int) $line : 1));
 50:         }
 51:     }
 52: 
 53: 
 54:     public static function formatHtml($mask)
 55:     {
 56:         $args = func_get_args();
 57:         return preg_replace_callback('#%#', function () use (& $args, & $count) {
 58:             return htmlspecialchars($args[++$count], ENT_IGNORE | ENT_QUOTES, 'UTF-8');
 59:         }, $mask);
 60:     }
 61: 
 62: 
 63:     public static function findTrace(array $trace, $method, & $index = NULL)
 64:     {
 65:         $m = explode('::', $method);
 66:         foreach ($trace as $i => $item) {
 67:             if (isset($item['function']) && $item['function'] === end($m)
 68:                 && isset($item['class']) === isset($m[1])
 69:                 && (!isset($item['class']) || $item['class'] === $m[0] || $m[0] === '*' || is_subclass_of($item['class'], $m[0]))
 70:             ) {
 71:                 $index = $i;
 72:                 return $item;
 73:             }
 74:         }
 75:     }
 76: 
 77: 
 78:     /**
 79:      * @return string
 80:      */
 81:     public static function getClass($obj)
 82:     {
 83:         return current(explode("\x00", get_class($obj)));
 84:     }
 85: 
 86: 
 87:     /** @internal */
 88:     public static function fixStack($exception)
 89:     {
 90:         if (function_exists('xdebug_get_function_stack')) {
 91:             $stack = array();
 92:             foreach (array_slice(array_reverse(xdebug_get_function_stack()), 2, -1) as $row) {
 93:                 $frame = array(
 94:                     'file' => $row['file'],
 95:                     'line' => $row['line'],
 96:                     'function' => isset($row['function']) ? $row['function'] : '*unknown*',
 97:                     'args' => array(),
 98:                 );
 99:                 if (!empty($row['class'])) {
100:                     $frame['type'] = isset($row['type']) && $row['type'] === 'dynamic' ? '->' : '::';
101:                     $frame['class'] = $row['class'];
102:                 }
103:                 $stack[] = $frame;
104:             }
105:             $ref = new \ReflectionProperty('Exception', 'trace');
106:             $ref->setAccessible(TRUE);
107:             $ref->setValue($exception, $stack);
108:         }
109:         return $exception;
110:     }
111: 
112: 
113:     /** @internal */
114:     public static function fixEncoding($s)
115:     {
116:         if (PHP_VERSION_ID < 50400) {
117:             return @iconv('UTF-16', 'UTF-8//IGNORE', iconv('UTF-8', 'UTF-16//IGNORE', $s)); // intentionally @
118:         } else {
119:             return htmlspecialchars_decode(htmlspecialchars($s, ENT_NOQUOTES | ENT_IGNORE, 'UTF-8'), ENT_NOQUOTES);
120:         }
121:     }
122: 
123: 
124:     /** @internal */
125:     public static function errorTypeToString($type)
126:     {
127:         $types = array(
128:             E_ERROR => 'Fatal Error',
129:             E_USER_ERROR => 'User Error',
130:             E_RECOVERABLE_ERROR => 'Recoverable Error',
131:             E_CORE_ERROR => 'Core Error',
132:             E_COMPILE_ERROR => 'Compile Error',
133:             E_PARSE => 'Parse Error',
134:             E_WARNING => 'Warning',
135:             E_CORE_WARNING => 'Core Warning',
136:             E_COMPILE_WARNING => 'Compile Warning',
137:             E_USER_WARNING => 'User Warning',
138:             E_NOTICE => 'Notice',
139:             E_USER_NOTICE => 'User Notice',
140:             E_STRICT => 'Strict standards',
141:             E_DEPRECATED => 'Deprecated',
142:             E_USER_DEPRECATED => 'User Deprecated',
143:         );
144:         return isset($types[$type]) ? $types[$type] : 'Unknown error';
145:     }
146: 
147: 
148:     /** @internal */
149:     public static function getSource()
150:     {
151:         if (isset($_SERVER['REQUEST_URI'])) {
152:             return (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://')
153:                 . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '')
154:                 . $_SERVER['REQUEST_URI'];
155:         } else {
156:             return empty($_SERVER['argv']) ? 'CLI' : 'CLI: ' . implode(' ', $_SERVER['argv']);
157:         }
158:     }
159: 
160: 
161:     /** @internal */
162:     public static function improveException($e)
163:     {
164:         $message = $e->getMessage();
165:         if (!$e instanceof \Error && !$e instanceof \ErrorException) {
166:             // do nothing
167:         } elseif (preg_match('#^Call to undefined function (\S+\\\\)?(\w+)\(#', $message, $m)) {
168:             $funcs = get_defined_functions();
169:             $funcs = array_merge($funcs['internal'], $funcs['user']);
170:             $hint = self::getSuggestion($funcs, $m[1] . $m[2]) ?: self::getSuggestion($funcs, $m[2]);
171:             $message .= ", did you mean $hint()?";
172: 
173:         } elseif (preg_match('#^Call to undefined method (\S+)::(\w+)#', $message, $m)) {
174:             $hint = self::getSuggestion(get_class_methods($m[1]), $m[2]);
175:             $message .= ", did you mean $hint()?";
176: 
177:         } elseif (preg_match('#^Undefined variable: (\w+)#', $message, $m) && !empty($e->context)) {
178:             $hint = self::getSuggestion(array_keys($e->context), $m[1]);
179:             $message = "Undefined variable $$m[1], did you mean $$hint?";
180: 
181:         } elseif (preg_match('#^Undefined property: (\S+)::\$(\w+)#', $message, $m)) {
182:             $rc = new \ReflectionClass($m[1]);
183:             $items = array_diff($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
184:             $hint = self::getSuggestion($items, $m[2]);
185:             $message .= ", did you mean $$hint?";
186: 
187:         } elseif (preg_match('#^Access to undeclared static property: (\S+)::\$(\w+)#', $message, $m)) {
188:             $rc = new \ReflectionClass($m[1]);
189:             $items = array_intersect($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
190:             $hint = self::getSuggestion($items, $m[2]);
191:             $message .= ", did you mean $$hint?";
192:         }
193: 
194:         if (isset($hint)) {
195:             $ref = new \ReflectionProperty($e, 'message');
196:             $ref->setAccessible(TRUE);
197:             $ref->setValue($e, $message);
198:         }
199:     }
200: 
201: 
202:     /**
203:      * Finds the best suggestion.
204:      * @return string|NULL
205:      * @internal
206:      */
207:     public static function getSuggestion(array $items, $value)
208:     {
209:         $best = NULL;
210:         $min = (strlen($value) / 4 + 1) * 10 + .1;
211:         foreach (array_unique($items, SORT_REGULAR) as $item) {
212:             $item = is_object($item) ? $item->getName() : $item;
213:             if (($len = levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) {
214:                 $min = $len;
215:                 $best = $item;
216:             }
217:         }
218:         return $best;
219:     }
220: 
221: }
222: 
Nette 2.3-20161221 API API documentation generated by ApiGen 2.8.0