Completed
Push — develop ( 8dee05 )
by Dmytro
20:08
created
core/vendor/tracy/tracy/examples/fatal-error.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@
 block discarded – undo
16 16
 <?php
17 17
 
18 18
 if (Debugger::$productionMode) {
19
-	echo '<p><b>For security reasons, Tracy is visible only on localhost. Look into the source code to see how to enable Tracy.</b></p>';
19
+    echo '<p><b>For security reasons, Tracy is visible only on localhost. Look into the source code to see how to enable Tracy.</b></p>';
20 20
 }
21 21
 
22 22
 require __DIR__ . '/assets/E_COMPILE_ERROR.php';
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/shortcuts.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -6,39 +6,39 @@
 block discarded – undo
6 6
  */
7 7
 
8 8
 if (!function_exists('dump')) {
9
-	/**
10
-	 * Tracy\Debugger::dump() shortcut.
11
-	 * @tracySkipLocation
12
-	 */
13
-	function dump($var)
14
-	{
15
-		array_map('Tracy\Debugger::dump', func_get_args());
16
-		return $var;
17
-	}
9
+    /**
10
+     * Tracy\Debugger::dump() shortcut.
11
+     * @tracySkipLocation
12
+     */
13
+    function dump($var)
14
+    {
15
+        array_map('Tracy\Debugger::dump', func_get_args());
16
+        return $var;
17
+    }
18 18
 }
19 19
 
20 20
 if (!function_exists('dumpe')) {
21
-	/**
22
-	 * Tracy\Debugger::dump() & exit shortcut.
23
-	 * @tracySkipLocation
24
-	 */
25
-	function dumpe($var)
26
-	{
27
-		array_map('Tracy\Debugger::dump', func_get_args());
28
-		if (!Tracy\Debugger::$productionMode) {
29
-			exit;
30
-		}
31
-	}
21
+    /**
22
+     * Tracy\Debugger::dump() & exit shortcut.
23
+     * @tracySkipLocation
24
+     */
25
+    function dumpe($var)
26
+    {
27
+        array_map('Tracy\Debugger::dump', func_get_args());
28
+        if (!Tracy\Debugger::$productionMode) {
29
+            exit;
30
+        }
31
+    }
32 32
 }
33 33
 
34 34
 if (!function_exists('bdump')) {
35
-	/**
36
-	 * Tracy\Debugger::barDump() shortcut.
37
-	 * @tracySkipLocation
38
-	 */
39
-	function bdump($var)
40
-	{
41
-		call_user_func_array('Tracy\Debugger::barDump', func_get_args());
42
-		return $var;
43
-	}
35
+    /**
36
+     * Tracy\Debugger::barDump() shortcut.
37
+     * @tracySkipLocation
38
+     */
39
+    function bdump($var)
40
+    {
41
+        call_user_func_array('Tracy\Debugger::barDump', func_get_args());
42
+        return $var;
43
+    }
44 44
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/Helpers.php 1 patch
Indentation   +304 added lines, -304 removed lines patch added patch discarded remove patch
@@ -14,308 +14,308 @@
 block discarded – undo
14 14
 class Helpers
15 15
 {
16 16
 
17
-	/**
18
-	 * Returns HTML link to editor.
19
-	 * @return string
20
-	 */
21
-	public static function editorLink($file, $line = null)
22
-	{
23
-		$file = strtr($origFile = $file, Debugger::$editorMapping);
24
-		if ($editor = self::editorUri($origFile, $line)) {
25
-			$file = strtr($file, '\\', '/');
26
-			if (preg_match('#(^[a-z]:)?/.{1,50}$#i', $file, $m) && strlen($file) > strlen($m[0])) {
27
-				$file = '...' . $m[0];
28
-			}
29
-			$file = strtr($file, '/', DIRECTORY_SEPARATOR);
30
-			return self::formatHtml('<a href="%" title="%">%<b>%</b>%</a>',
31
-				$editor,
32
-				$file . ($line ? ":$line" : ''),
33
-				rtrim(dirname($file), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
34
-				basename($file),
35
-				$line ? ":$line" : ''
36
-			);
37
-		} else {
38
-			return self::formatHtml('<span>%</span>', $file . ($line ? ":$line" : ''));
39
-		}
40
-	}
41
-
42
-
43
-	/**
44
-	 * Returns link to editor.
45
-	 * @return string|null
46
-	 */
47
-	public static function editorUri($file, $line = null, $action = 'open', $search = null, $replace = null)
48
-	{
49
-		if (Debugger::$editor && $file && ($action === 'create' || is_file($file))) {
50
-			$file = strtr($file, '/', DIRECTORY_SEPARATOR);
51
-			$file = strtr($file, Debugger::$editorMapping);
52
-			return strtr(Debugger::$editor, [
53
-				'%action' => $action,
54
-				'%file' => rawurlencode($file),
55
-				'%line' => $line ? (int) $line : 1,
56
-				'%search' => rawurlencode($search),
57
-				'%replace' => rawurlencode($replace),
58
-			]);
59
-		}
60
-	}
61
-
62
-
63
-	public static function formatHtml($mask)
64
-	{
65
-		$args = func_get_args();
66
-		return preg_replace_callback('#%#', function () use (&$args, &$count) {
67
-			return self::escapeHtml($args[++$count]);
68
-		}, $mask);
69
-	}
70
-
71
-
72
-	public static function escapeHtml($s)
73
-	{
74
-		return htmlspecialchars((string) $s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
75
-	}
76
-
77
-
78
-	public static function findTrace(array $trace, $method, &$index = null)
79
-	{
80
-		$m = explode('::', $method);
81
-		foreach ($trace as $i => $item) {
82
-			if (
83
-				isset($item['function'])
84
-				&& $item['function'] === end($m)
85
-				&& isset($item['class']) === isset($m[1])
86
-				&& (!isset($item['class']) || $m[0] === '*' || is_a($item['class'], $m[0], true))
87
-			) {
88
-				$index = $i;
89
-				return $item;
90
-			}
91
-		}
92
-	}
93
-
94
-
95
-	/**
96
-	 * @return string
97
-	 */
98
-	public static function getClass($obj)
99
-	{
100
-		return explode("\x00", get_class($obj))[0];
101
-	}
102
-
103
-
104
-	/** @internal */
105
-	public static function fixStack($exception)
106
-	{
107
-		if (function_exists('xdebug_get_function_stack')) {
108
-			$stack = [];
109
-			foreach (array_slice(array_reverse(xdebug_get_function_stack()), 2, -1) as $row) {
110
-				$frame = [
111
-					'file' => $row['file'],
112
-					'line' => $row['line'],
113
-					'function' => isset($row['function']) ? $row['function'] : '*unknown*',
114
-					'args' => [],
115
-				];
116
-				if (!empty($row['class'])) {
117
-					$frame['type'] = isset($row['type']) && $row['type'] === 'dynamic' ? '->' : '::';
118
-					$frame['class'] = $row['class'];
119
-				}
120
-				$stack[] = $frame;
121
-			}
122
-			$ref = new \ReflectionProperty('Exception', 'trace');
123
-			$ref->setAccessible(true);
124
-			$ref->setValue($exception, $stack);
125
-		}
126
-		return $exception;
127
-	}
128
-
129
-
130
-	/** @internal */
131
-	public static function fixEncoding($s)
132
-	{
133
-		return htmlspecialchars_decode(htmlspecialchars($s, ENT_NOQUOTES | ENT_IGNORE, 'UTF-8'), ENT_NOQUOTES);
134
-	}
135
-
136
-
137
-	/** @internal */
138
-	public static function errorTypeToString($type)
139
-	{
140
-		$types = [
141
-			E_ERROR => 'Fatal Error',
142
-			E_USER_ERROR => 'User Error',
143
-			E_RECOVERABLE_ERROR => 'Recoverable Error',
144
-			E_CORE_ERROR => 'Core Error',
145
-			E_COMPILE_ERROR => 'Compile Error',
146
-			E_PARSE => 'Parse Error',
147
-			E_WARNING => 'Warning',
148
-			E_CORE_WARNING => 'Core Warning',
149
-			E_COMPILE_WARNING => 'Compile Warning',
150
-			E_USER_WARNING => 'User Warning',
151
-			E_NOTICE => 'Notice',
152
-			E_USER_NOTICE => 'User Notice',
153
-			E_STRICT => 'Strict standards',
154
-			E_DEPRECATED => 'Deprecated',
155
-			E_USER_DEPRECATED => 'User Deprecated',
156
-		];
157
-		return isset($types[$type]) ? $types[$type] : 'Unknown error';
158
-	}
159
-
160
-
161
-	/** @internal */
162
-	public static function getSource()
163
-	{
164
-		if (isset($_SERVER['REQUEST_URI'])) {
165
-			return (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://')
166
-				. (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '')
167
-				. $_SERVER['REQUEST_URI'];
168
-		} else {
169
-			return 'CLI (PID: ' . getmypid() . ')'
170
-				. (empty($_SERVER['argv']) ? '' : ': ' . implode(' ', $_SERVER['argv']));
171
-		}
172
-	}
173
-
174
-
175
-	/** @internal */
176
-	public static function improveException($e)
177
-	{
178
-		$message = $e->getMessage();
179
-
180
-		if ($e instanceof \Nette\MemberAccessException && ($trace = $e->getTrace()) && isset($trace[1]['file'], $trace[1]['line'])) {
181
-			if (preg_match('# property ([\w\\\\]+)::\$(\w+), did you mean \$(\w+)#', $message, $m)) {
182
-				$replace = ["->$m[2]", "->$m[3]"];
183
-			} elseif (preg_match('# method ([\w\\\\]+)::(\w+)\(\), did you mean (\w+)\(#', $message, $m)) {
184
-				$replace = ["$m[2](", "$m[3]("];
185
-			} else {
186
-				return;
187
-			}
188
-			$e->tracyAction = [
189
-				'link' => self::editorUri($trace[1]['file'], $trace[1]['line'], 'fix', $replace[0], $replace[1]),
190
-				'label' => 'fix it',
191
-			];
192
-
193
-		} elseif (!$e instanceof \Error && !$e instanceof \ErrorException) {
194
-			// do nothing
195
-		} elseif (preg_match('#^Call to undefined function (\S+\\\\)?(\w+)\(#', $message, $m)) {
196
-			$funcs = array_merge(get_defined_functions()['internal'], get_defined_functions()['user']);
197
-			$hint = self::getSuggestion($funcs, $m[1] . $m[2]) ?: self::getSuggestion($funcs, $m[2]);
198
-			$message = "Call to undefined function $m[2](), did you mean $hint()?";
199
-			$replace = ["$m[2](", "$hint("];
200
-
201
-		} elseif (preg_match('#^Call to undefined method ([\w\\\\]+)::(\w+)#', $message, $m)) {
202
-			$hint = self::getSuggestion(get_class_methods($m[1]), $m[2]);
203
-			$message .= ", did you mean $hint()?";
204
-			$replace = ["$m[2](", "$hint("];
205
-
206
-		} elseif (preg_match('#^Undefined variable: (\w+)#', $message, $m) && !empty($e->context)) {
207
-			$hint = self::getSuggestion(array_keys($e->context), $m[1]);
208
-			$message = "Undefined variable $$m[1], did you mean $$hint?";
209
-			$replace = ["$$m[1]", "$$hint"];
210
-
211
-		} elseif (preg_match('#^Undefined property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
212
-			$rc = new \ReflectionClass($m[1]);
213
-			$items = array_diff($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
214
-			$hint = self::getSuggestion($items, $m[2]);
215
-			$message .= ", did you mean $$hint?";
216
-			$replace = ["->$m[2]", "->$hint"];
217
-
218
-		} elseif (preg_match('#^Access to undeclared static property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
219
-			$rc = new \ReflectionClass($m[1]);
220
-			$items = array_intersect($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
221
-			$hint = self::getSuggestion($items, $m[2]);
222
-			$message .= ", did you mean $$hint?";
223
-			$replace = ["::$$m[2]", "::$$hint"];
224
-		}
225
-
226
-		if (isset($hint)) {
227
-			$ref = new \ReflectionProperty($e, 'message');
228
-			$ref->setAccessible(true);
229
-			$ref->setValue($e, $message);
230
-			$e->tracyAction = [
231
-				'link' => self::editorUri($e->getFile(), $e->getLine(), 'fix', $replace[0], $replace[1]),
232
-				'label' => 'fix it',
233
-			];
234
-		}
235
-	}
236
-
237
-
238
-	/** @internal */
239
-	public static function improveError($message, array $context = [])
240
-	{
241
-		if (preg_match('#^Undefined variable: (\w+)#', $message, $m) && $context) {
242
-			$hint = self::getSuggestion(array_keys($context), $m[1]);
243
-			return $hint ? "Undefined variable $$m[1], did you mean $$hint?" : $message;
244
-
245
-		} elseif (preg_match('#^Undefined property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
246
-			$rc = new \ReflectionClass($m[1]);
247
-			$items = array_diff($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
248
-			$hint = self::getSuggestion($items, $m[2]);
249
-			return $hint ? $message . ", did you mean $$hint?" : $message;
250
-		}
251
-		return $message;
252
-	}
253
-
254
-
255
-	/** @internal */
256
-	public static function guessClassFile($class)
257
-	{
258
-		$segments = explode(DIRECTORY_SEPARATOR, $class);
259
-		$res = null;
260
-		$max = 0;
261
-		foreach (get_declared_classes() as $class) {
262
-			$parts = explode(DIRECTORY_SEPARATOR, $class);
263
-			foreach ($parts as $i => $part) {
264
-				if (!isset($segments[$i]) || $part !== $segments[$i]) {
265
-					break;
266
-				}
267
-			}
268
-			if ($i > $max && ($file = (new \ReflectionClass($class))->getFileName())) {
269
-				$max = $i;
270
-				$res = array_merge(array_slice(explode(DIRECTORY_SEPARATOR, $file), 0, $i - count($parts)), array_slice($segments, $i));
271
-				$res = implode(DIRECTORY_SEPARATOR, $res) . '.php';
272
-			}
273
-		}
274
-		return $res;
275
-	}
276
-
277
-
278
-	/**
279
-	 * Finds the best suggestion.
280
-	 * @return string|null
281
-	 * @internal
282
-	 */
283
-	public static function getSuggestion(array $items, $value)
284
-	{
285
-		$best = null;
286
-		$min = (strlen($value) / 4 + 1) * 10 + .1;
287
-		foreach (array_unique($items, SORT_REGULAR) as $item) {
288
-			$item = is_object($item) ? $item->getName() : $item;
289
-			if (($len = levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) {
290
-				$min = $len;
291
-				$best = $item;
292
-			}
293
-		}
294
-		return $best;
295
-	}
296
-
297
-
298
-	/** @internal */
299
-	public static function isHtmlMode()
300
-	{
301
-		return empty($_SERVER['HTTP_X_REQUESTED_WITH']) && empty($_SERVER['HTTP_X_TRACY_AJAX'])
302
-			&& PHP_SAPI !== 'cli'
303
-			&& !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()));
304
-	}
305
-
306
-
307
-	/** @internal */
308
-	public static function isAjax()
309
-	{
310
-		return isset($_SERVER['HTTP_X_TRACY_AJAX']) && preg_match('#^\w{10}\z#', $_SERVER['HTTP_X_TRACY_AJAX']);
311
-	}
312
-
313
-
314
-	/** @internal */
315
-	public static function getNonce()
316
-	{
317
-		return preg_match('#^Content-Security-Policy(?:-Report-Only)?:.*\sscript-src\s+(?:[^;]+\s)?\'nonce-([\w+/]+=*)\'#mi', implode("\n", headers_list()), $m)
318
-			? $m[1]
319
-			: null;
320
-	}
17
+    /**
18
+     * Returns HTML link to editor.
19
+     * @return string
20
+     */
21
+    public static function editorLink($file, $line = null)
22
+    {
23
+        $file = strtr($origFile = $file, Debugger::$editorMapping);
24
+        if ($editor = self::editorUri($origFile, $line)) {
25
+            $file = strtr($file, '\\', '/');
26
+            if (preg_match('#(^[a-z]:)?/.{1,50}$#i', $file, $m) && strlen($file) > strlen($m[0])) {
27
+                $file = '...' . $m[0];
28
+            }
29
+            $file = strtr($file, '/', DIRECTORY_SEPARATOR);
30
+            return self::formatHtml('<a href="%" title="%">%<b>%</b>%</a>',
31
+                $editor,
32
+                $file . ($line ? ":$line" : ''),
33
+                rtrim(dirname($file), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
34
+                basename($file),
35
+                $line ? ":$line" : ''
36
+            );
37
+        } else {
38
+            return self::formatHtml('<span>%</span>', $file . ($line ? ":$line" : ''));
39
+        }
40
+    }
41
+
42
+
43
+    /**
44
+     * Returns link to editor.
45
+     * @return string|null
46
+     */
47
+    public static function editorUri($file, $line = null, $action = 'open', $search = null, $replace = null)
48
+    {
49
+        if (Debugger::$editor && $file && ($action === 'create' || is_file($file))) {
50
+            $file = strtr($file, '/', DIRECTORY_SEPARATOR);
51
+            $file = strtr($file, Debugger::$editorMapping);
52
+            return strtr(Debugger::$editor, [
53
+                '%action' => $action,
54
+                '%file' => rawurlencode($file),
55
+                '%line' => $line ? (int) $line : 1,
56
+                '%search' => rawurlencode($search),
57
+                '%replace' => rawurlencode($replace),
58
+            ]);
59
+        }
60
+    }
61
+
62
+
63
+    public static function formatHtml($mask)
64
+    {
65
+        $args = func_get_args();
66
+        return preg_replace_callback('#%#', function () use (&$args, &$count) {
67
+            return self::escapeHtml($args[++$count]);
68
+        }, $mask);
69
+    }
70
+
71
+
72
+    public static function escapeHtml($s)
73
+    {
74
+        return htmlspecialchars((string) $s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
75
+    }
76
+
77
+
78
+    public static function findTrace(array $trace, $method, &$index = null)
79
+    {
80
+        $m = explode('::', $method);
81
+        foreach ($trace as $i => $item) {
82
+            if (
83
+                isset($item['function'])
84
+                && $item['function'] === end($m)
85
+                && isset($item['class']) === isset($m[1])
86
+                && (!isset($item['class']) || $m[0] === '*' || is_a($item['class'], $m[0], true))
87
+            ) {
88
+                $index = $i;
89
+                return $item;
90
+            }
91
+        }
92
+    }
93
+
94
+
95
+    /**
96
+     * @return string
97
+     */
98
+    public static function getClass($obj)
99
+    {
100
+        return explode("\x00", get_class($obj))[0];
101
+    }
102
+
103
+
104
+    /** @internal */
105
+    public static function fixStack($exception)
106
+    {
107
+        if (function_exists('xdebug_get_function_stack')) {
108
+            $stack = [];
109
+            foreach (array_slice(array_reverse(xdebug_get_function_stack()), 2, -1) as $row) {
110
+                $frame = [
111
+                    'file' => $row['file'],
112
+                    'line' => $row['line'],
113
+                    'function' => isset($row['function']) ? $row['function'] : '*unknown*',
114
+                    'args' => [],
115
+                ];
116
+                if (!empty($row['class'])) {
117
+                    $frame['type'] = isset($row['type']) && $row['type'] === 'dynamic' ? '->' : '::';
118
+                    $frame['class'] = $row['class'];
119
+                }
120
+                $stack[] = $frame;
121
+            }
122
+            $ref = new \ReflectionProperty('Exception', 'trace');
123
+            $ref->setAccessible(true);
124
+            $ref->setValue($exception, $stack);
125
+        }
126
+        return $exception;
127
+    }
128
+
129
+
130
+    /** @internal */
131
+    public static function fixEncoding($s)
132
+    {
133
+        return htmlspecialchars_decode(htmlspecialchars($s, ENT_NOQUOTES | ENT_IGNORE, 'UTF-8'), ENT_NOQUOTES);
134
+    }
135
+
136
+
137
+    /** @internal */
138
+    public static function errorTypeToString($type)
139
+    {
140
+        $types = [
141
+            E_ERROR => 'Fatal Error',
142
+            E_USER_ERROR => 'User Error',
143
+            E_RECOVERABLE_ERROR => 'Recoverable Error',
144
+            E_CORE_ERROR => 'Core Error',
145
+            E_COMPILE_ERROR => 'Compile Error',
146
+            E_PARSE => 'Parse Error',
147
+            E_WARNING => 'Warning',
148
+            E_CORE_WARNING => 'Core Warning',
149
+            E_COMPILE_WARNING => 'Compile Warning',
150
+            E_USER_WARNING => 'User Warning',
151
+            E_NOTICE => 'Notice',
152
+            E_USER_NOTICE => 'User Notice',
153
+            E_STRICT => 'Strict standards',
154
+            E_DEPRECATED => 'Deprecated',
155
+            E_USER_DEPRECATED => 'User Deprecated',
156
+        ];
157
+        return isset($types[$type]) ? $types[$type] : 'Unknown error';
158
+    }
159
+
160
+
161
+    /** @internal */
162
+    public static function getSource()
163
+    {
164
+        if (isset($_SERVER['REQUEST_URI'])) {
165
+            return (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://')
166
+                . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '')
167
+                . $_SERVER['REQUEST_URI'];
168
+        } else {
169
+            return 'CLI (PID: ' . getmypid() . ')'
170
+                . (empty($_SERVER['argv']) ? '' : ': ' . implode(' ', $_SERVER['argv']));
171
+        }
172
+    }
173
+
174
+
175
+    /** @internal */
176
+    public static function improveException($e)
177
+    {
178
+        $message = $e->getMessage();
179
+
180
+        if ($e instanceof \Nette\MemberAccessException && ($trace = $e->getTrace()) && isset($trace[1]['file'], $trace[1]['line'])) {
181
+            if (preg_match('# property ([\w\\\\]+)::\$(\w+), did you mean \$(\w+)#', $message, $m)) {
182
+                $replace = ["->$m[2]", "->$m[3]"];
183
+            } elseif (preg_match('# method ([\w\\\\]+)::(\w+)\(\), did you mean (\w+)\(#', $message, $m)) {
184
+                $replace = ["$m[2](", "$m[3]("];
185
+            } else {
186
+                return;
187
+            }
188
+            $e->tracyAction = [
189
+                'link' => self::editorUri($trace[1]['file'], $trace[1]['line'], 'fix', $replace[0], $replace[1]),
190
+                'label' => 'fix it',
191
+            ];
192
+
193
+        } elseif (!$e instanceof \Error && !$e instanceof \ErrorException) {
194
+            // do nothing
195
+        } elseif (preg_match('#^Call to undefined function (\S+\\\\)?(\w+)\(#', $message, $m)) {
196
+            $funcs = array_merge(get_defined_functions()['internal'], get_defined_functions()['user']);
197
+            $hint = self::getSuggestion($funcs, $m[1] . $m[2]) ?: self::getSuggestion($funcs, $m[2]);
198
+            $message = "Call to undefined function $m[2](), did you mean $hint()?";
199
+            $replace = ["$m[2](", "$hint("];
200
+
201
+        } elseif (preg_match('#^Call to undefined method ([\w\\\\]+)::(\w+)#', $message, $m)) {
202
+            $hint = self::getSuggestion(get_class_methods($m[1]), $m[2]);
203
+            $message .= ", did you mean $hint()?";
204
+            $replace = ["$m[2](", "$hint("];
205
+
206
+        } elseif (preg_match('#^Undefined variable: (\w+)#', $message, $m) && !empty($e->context)) {
207
+            $hint = self::getSuggestion(array_keys($e->context), $m[1]);
208
+            $message = "Undefined variable $$m[1], did you mean $$hint?";
209
+            $replace = ["$$m[1]", "$$hint"];
210
+
211
+        } elseif (preg_match('#^Undefined property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
212
+            $rc = new \ReflectionClass($m[1]);
213
+            $items = array_diff($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
214
+            $hint = self::getSuggestion($items, $m[2]);
215
+            $message .= ", did you mean $$hint?";
216
+            $replace = ["->$m[2]", "->$hint"];
217
+
218
+        } elseif (preg_match('#^Access to undeclared static property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
219
+            $rc = new \ReflectionClass($m[1]);
220
+            $items = array_intersect($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
221
+            $hint = self::getSuggestion($items, $m[2]);
222
+            $message .= ", did you mean $$hint?";
223
+            $replace = ["::$$m[2]", "::$$hint"];
224
+        }
225
+
226
+        if (isset($hint)) {
227
+            $ref = new \ReflectionProperty($e, 'message');
228
+            $ref->setAccessible(true);
229
+            $ref->setValue($e, $message);
230
+            $e->tracyAction = [
231
+                'link' => self::editorUri($e->getFile(), $e->getLine(), 'fix', $replace[0], $replace[1]),
232
+                'label' => 'fix it',
233
+            ];
234
+        }
235
+    }
236
+
237
+
238
+    /** @internal */
239
+    public static function improveError($message, array $context = [])
240
+    {
241
+        if (preg_match('#^Undefined variable: (\w+)#', $message, $m) && $context) {
242
+            $hint = self::getSuggestion(array_keys($context), $m[1]);
243
+            return $hint ? "Undefined variable $$m[1], did you mean $$hint?" : $message;
244
+
245
+        } elseif (preg_match('#^Undefined property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
246
+            $rc = new \ReflectionClass($m[1]);
247
+            $items = array_diff($rc->getProperties(\ReflectionProperty::IS_PUBLIC), $rc->getProperties(\ReflectionProperty::IS_STATIC));
248
+            $hint = self::getSuggestion($items, $m[2]);
249
+            return $hint ? $message . ", did you mean $$hint?" : $message;
250
+        }
251
+        return $message;
252
+    }
253
+
254
+
255
+    /** @internal */
256
+    public static function guessClassFile($class)
257
+    {
258
+        $segments = explode(DIRECTORY_SEPARATOR, $class);
259
+        $res = null;
260
+        $max = 0;
261
+        foreach (get_declared_classes() as $class) {
262
+            $parts = explode(DIRECTORY_SEPARATOR, $class);
263
+            foreach ($parts as $i => $part) {
264
+                if (!isset($segments[$i]) || $part !== $segments[$i]) {
265
+                    break;
266
+                }
267
+            }
268
+            if ($i > $max && ($file = (new \ReflectionClass($class))->getFileName())) {
269
+                $max = $i;
270
+                $res = array_merge(array_slice(explode(DIRECTORY_SEPARATOR, $file), 0, $i - count($parts)), array_slice($segments, $i));
271
+                $res = implode(DIRECTORY_SEPARATOR, $res) . '.php';
272
+            }
273
+        }
274
+        return $res;
275
+    }
276
+
277
+
278
+    /**
279
+     * Finds the best suggestion.
280
+     * @return string|null
281
+     * @internal
282
+     */
283
+    public static function getSuggestion(array $items, $value)
284
+    {
285
+        $best = null;
286
+        $min = (strlen($value) / 4 + 1) * 10 + .1;
287
+        foreach (array_unique($items, SORT_REGULAR) as $item) {
288
+            $item = is_object($item) ? $item->getName() : $item;
289
+            if (($len = levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) {
290
+                $min = $len;
291
+                $best = $item;
292
+            }
293
+        }
294
+        return $best;
295
+    }
296
+
297
+
298
+    /** @internal */
299
+    public static function isHtmlMode()
300
+    {
301
+        return empty($_SERVER['HTTP_X_REQUESTED_WITH']) && empty($_SERVER['HTTP_X_TRACY_AJAX'])
302
+            && PHP_SAPI !== 'cli'
303
+            && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()));
304
+    }
305
+
306
+
307
+    /** @internal */
308
+    public static function isAjax()
309
+    {
310
+        return isset($_SERVER['HTTP_X_TRACY_AJAX']) && preg_match('#^\w{10}\z#', $_SERVER['HTTP_X_TRACY_AJAX']);
311
+    }
312
+
313
+
314
+    /** @internal */
315
+    public static function getNonce()
316
+    {
317
+        return preg_match('#^Content-Security-Policy(?:-Report-Only)?:.*\sscript-src\s+(?:[^;]+\s)?\'nonce-([\w+/]+=*)\'#mi', implode("\n", headers_list()), $m)
318
+            ? $m[1]
319
+            : null;
320
+    }
321 321
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/Dumper.php 1 patch
Indentation   +579 added lines, -579 removed lines patch added patch discarded remove patch
@@ -13,583 +13,583 @@
 block discarded – undo
13 13
  */
14 14
 class Dumper
15 15
 {
16
-	const
17
-		DEPTH = 'depth', // how many nested levels of array/object properties display (defaults to 4)
18
-		TRUNCATE = 'truncate', // how truncate long strings? (defaults to 150)
19
-		COLLAPSE = 'collapse', // collapse top array/object or how big are collapsed? (defaults to 14)
20
-		COLLAPSE_COUNT = 'collapsecount', // how big array/object are collapsed? (defaults to 7)
21
-		LOCATION = 'location', // show location string? (defaults to 0)
22
-		OBJECT_EXPORTERS = 'exporters', // custom exporters for objects (defaults to Dumper::$objectexporters)
23
-		LIVE = 'live', // will be rendered using JavaScript
24
-		DEBUGINFO = 'debuginfo', // use magic method __debugInfo if exists (defaults to false)
25
-		KEYS_TO_HIDE = 'keystohide'; // sensitive keys not displayed (defaults to [])
26
-
27
-	const
28
-		LOCATION_SOURCE = 0b0001, // shows where dump was called
29
-		LOCATION_LINK = 0b0010, // appends clickable anchor
30
-		LOCATION_CLASS = 0b0100; // shows where class is defined
31
-
32
-	const
33
-		HIDDEN_VALUE = '*****';
34
-
35
-	/** @var array */
36
-	public static $terminalColors = [
37
-		'bool' => '1;33',
38
-		'null' => '1;33',
39
-		'number' => '1;32',
40
-		'string' => '1;36',
41
-		'array' => '1;31',
42
-		'key' => '1;37',
43
-		'object' => '1;31',
44
-		'visibility' => '1;30',
45
-		'resource' => '1;37',
46
-		'indent' => '1;30',
47
-	];
48
-
49
-	/** @var array */
50
-	public static $resources = [
51
-		'stream' => 'stream_get_meta_data',
52
-		'stream-context' => 'stream_context_get_options',
53
-		'curl' => 'curl_getinfo',
54
-	];
55
-
56
-	/** @var array */
57
-	public static $objectExporters = [
58
-		'Closure' => 'Tracy\Dumper::exportClosure',
59
-		'SplFileInfo' => 'Tracy\Dumper::exportSplFileInfo',
60
-		'SplObjectStorage' => 'Tracy\Dumper::exportSplObjectStorage',
61
-		'__PHP_Incomplete_Class' => 'Tracy\Dumper::exportPhpIncompleteClass',
62
-	];
63
-
64
-	/** @var string @internal */
65
-	public static $livePrefix;
66
-
67
-	/** @var array  */
68
-	private static $liveStorage = [];
69
-
70
-
71
-	/**
72
-	 * Dumps variable to the output.
73
-	 * @return mixed  variable
74
-	 */
75
-	public static function dump($var, array $options = null)
76
-	{
77
-		if (PHP_SAPI !== 'cli' && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()))) {
78
-			echo self::toHtml($var, $options);
79
-		} elseif (self::detectColors()) {
80
-			echo self::toTerminal($var, $options);
81
-		} else {
82
-			echo self::toText($var, $options);
83
-		}
84
-		return $var;
85
-	}
86
-
87
-
88
-	/**
89
-	 * Dumps variable to HTML.
90
-	 * @return string
91
-	 */
92
-	public static function toHtml($var, array $options = null)
93
-	{
94
-		$options = (array) $options + [
95
-			self::DEPTH => 4,
96
-			self::TRUNCATE => 150,
97
-			self::COLLAPSE => 14,
98
-			self::COLLAPSE_COUNT => 7,
99
-			self::OBJECT_EXPORTERS => null,
100
-			self::DEBUGINFO => false,
101
-			self::KEYS_TO_HIDE => [],
102
-		];
103
-		$loc = &$options[self::LOCATION];
104
-		$loc = $loc === true ? ~0 : (int) $loc;
105
-
106
-		$options[self::KEYS_TO_HIDE] = array_flip(array_map('strtolower', $options[self::KEYS_TO_HIDE]));
107
-		$options[self::OBJECT_EXPORTERS] = (array) $options[self::OBJECT_EXPORTERS] + self::$objectExporters;
108
-		uksort($options[self::OBJECT_EXPORTERS], function ($a, $b) {
109
-			return $b === '' || (class_exists($a, false) && is_subclass_of($a, $b)) ? -1 : 1;
110
-		});
111
-
112
-		$live = !empty($options[self::LIVE]) && $var && (is_array($var) || is_object($var) || is_resource($var));
113
-		list($file, $line, $code) = $loc ? self::findLocation() : null;
114
-		$locAttrs = $file && $loc & self::LOCATION_SOURCE ? Helpers::formatHtml(
115
-			' title="%in file % on line %" data-tracy-href="%"', "$code\n", $file, $line, Helpers::editorUri($file, $line)
116
-		) : null;
117
-
118
-		return '<pre class="tracy-dump' . ($live && $options[self::COLLAPSE] === true ? ' tracy-collapsed' : '') . '"'
119
-			. $locAttrs
120
-			. ($live ? " data-tracy-dump='" . json_encode(self::toJson($var, $options), JSON_HEX_APOS | JSON_HEX_AMP) . "'>" : '>')
121
-			. ($live ? '' : self::dumpVar($var, $options))
122
-			. ($file && $loc & self::LOCATION_LINK ? '<small>in ' . Helpers::editorLink($file, $line) . '</small>' : '')
123
-			. "</pre>\n";
124
-	}
125
-
126
-
127
-	/**
128
-	 * Dumps variable to plain text.
129
-	 * @return string
130
-	 */
131
-	public static function toText($var, array $options = null)
132
-	{
133
-		return htmlspecialchars_decode(strip_tags(self::toHtml($var, $options)), ENT_QUOTES);
134
-	}
135
-
136
-
137
-	/**
138
-	 * Dumps variable to x-terminal.
139
-	 * @return string
140
-	 */
141
-	public static function toTerminal($var, array $options = null)
142
-	{
143
-		return htmlspecialchars_decode(strip_tags(preg_replace_callback('#<span class="tracy-dump-(\w+)">|</span>#', function ($m) {
144
-			return "\033[" . (isset($m[1], self::$terminalColors[$m[1]]) ? self::$terminalColors[$m[1]] : '0') . 'm';
145
-		}, self::toHtml($var, $options))), ENT_QUOTES);
146
-	}
147
-
148
-
149
-	/**
150
-	 * Internal toHtml() dump implementation.
151
-	 * @param  mixed  $var
152
-	 * @param  array  $options
153
-	 * @param  int  $level  recursion level
154
-	 * @return string
155
-	 */
156
-	private static function dumpVar(&$var, array $options, $level = 0)
157
-	{
158
-		if (method_exists(__CLASS__, $m = 'dump' . gettype($var))) {
159
-			return self::$m($var, $options, $level);
160
-		} else {
161
-			return "<span>unknown type</span>\n";
162
-		}
163
-	}
164
-
165
-
166
-	private static function dumpNull()
167
-	{
168
-		return "<span class=\"tracy-dump-null\">null</span>\n";
169
-	}
170
-
171
-
172
-	private static function dumpBoolean(&$var)
173
-	{
174
-		return '<span class="tracy-dump-bool">' . ($var ? 'true' : 'false') . "</span>\n";
175
-	}
176
-
177
-
178
-	private static function dumpInteger(&$var)
179
-	{
180
-		return "<span class=\"tracy-dump-number\">$var</span>\n";
181
-	}
182
-
183
-
184
-	private static function dumpDouble(&$var)
185
-	{
186
-		$var = is_finite($var)
187
-			? ($tmp = json_encode($var)) . (strpos($tmp, '.') === false ? '.0' : '')
188
-			: str_replace('.0', '', var_export($var, true)); // workaround for PHP 7.0.2
189
-		return "<span class=\"tracy-dump-number\">$var</span>\n";
190
-	}
191
-
192
-
193
-	private static function dumpString(&$var, $options)
194
-	{
195
-		return '<span class="tracy-dump-string">"'
196
-			. Helpers::escapeHtml(self::encodeString($var, $options[self::TRUNCATE]))
197
-			. '"</span>' . (strlen($var) > 1 ? ' (' . strlen($var) . ')' : '') . "\n";
198
-	}
199
-
200
-
201
-	private static function dumpArray(&$var, $options, $level)
202
-	{
203
-		static $marker;
204
-		if ($marker === null) {
205
-			$marker = uniqid("\x00", true);
206
-		}
207
-
208
-		$out = '<span class="tracy-dump-array">array</span> (';
209
-
210
-		if (empty($var)) {
211
-			return $out . ")\n";
212
-
213
-		} elseif (isset($var[$marker])) {
214
-			return $out . (count($var) - 1) . ") [ <i>RECURSION</i> ]\n";
215
-
216
-		} elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH]) {
217
-			$collapsed = $level ? count($var) >= $options[self::COLLAPSE_COUNT]
218
-				: (is_int($options[self::COLLAPSE]) ? count($var) >= $options[self::COLLAPSE] : $options[self::COLLAPSE]);
219
-			$out = '<span class="tracy-toggle' . ($collapsed ? ' tracy-collapsed' : '') . '">'
220
-				. $out . count($var) . ")</span>\n<div" . ($collapsed ? ' class="tracy-collapsed"' : '') . '>';
221
-			$var[$marker] = true;
222
-			foreach ($var as $k => &$v) {
223
-				if ($k !== $marker) {
224
-					$hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]) ? self::HIDDEN_VALUE : null;
225
-					$k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . Helpers::escapeHtml(self::encodeString($k, $options[self::TRUNCATE])) . '"';
226
-					$out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
227
-						. '<span class="tracy-dump-key">' . $k . '</span> => '
228
-						. ($hide ? self::dumpString($hide, $options) : self::dumpVar($v, $options, $level + 1));
229
-				}
230
-			}
231
-			unset($var[$marker]);
232
-			return $out . '</div>';
233
-
234
-		} else {
235
-			return $out . count($var) . ") [ ... ]\n";
236
-		}
237
-	}
238
-
239
-
240
-	private static function dumpObject(&$var, $options, $level)
241
-	{
242
-		$fields = self::exportObject($var, $options[self::OBJECT_EXPORTERS], $options[self::DEBUGINFO]);
243
-
244
-		$editorAttributes = '';
245
-		if ($options[self::LOCATION] & self::LOCATION_CLASS) {
246
-			$rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var);
247
-			$editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine());
248
-			if ($editor) {
249
-				$editorAttributes = Helpers::formatHtml(
250
-					' title="Declared in file % on line %" data-tracy-href="%"',
251
-					$rc->getFileName(),
252
-					$rc->getStartLine(),
253
-					$editor
254
-				);
255
-			}
256
-		}
257
-		$out = '<span class="tracy-dump-object"' . $editorAttributes . '>'
258
-			. Helpers::escapeHtml(Helpers::getClass($var))
259
-			. '</span> <span class="tracy-dump-hash">#' . substr(md5(spl_object_hash($var)), 0, 4) . '</span>';
260
-
261
-		static $list = [];
262
-
263
-		if (empty($fields)) {
264
-			return $out . "\n";
265
-
266
-		} elseif (in_array($var, $list, true)) {
267
-			return $out . " { <i>RECURSION</i> }\n";
268
-
269
-		} elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH] || $var instanceof \Closure) {
270
-			$collapsed = $level ? count($fields) >= $options[self::COLLAPSE_COUNT]
271
-				: (is_int($options[self::COLLAPSE]) ? count($fields) >= $options[self::COLLAPSE] : $options[self::COLLAPSE]);
272
-			$out = '<span class="tracy-toggle' . ($collapsed ? ' tracy-collapsed' : '') . '">'
273
-				. $out . "</span>\n<div" . ($collapsed ? ' class="tracy-collapsed"' : '') . '>';
274
-			$list[] = $var;
275
-			foreach ($fields as $k => &$v) {
276
-				$vis = '';
277
-				if (isset($k[0]) && $k[0] === "\x00") {
278
-					$vis = ' <span class="tracy-dump-visibility">' . ($k[1] === '*' ? 'protected' : 'private') . '</span>';
279
-					$k = substr($k, strrpos($k, "\x00") + 1);
280
-				}
281
-				$hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]) ? self::HIDDEN_VALUE : null;
282
-				$k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . Helpers::escapeHtml(self::encodeString($k, $options[self::TRUNCATE])) . '"';
283
-				$out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
284
-					. '<span class="tracy-dump-key">' . $k . "</span>$vis => "
285
-					. ($hide ? self::dumpString($hide, $options) : self::dumpVar($v, $options, $level + 1));
286
-			}
287
-			array_pop($list);
288
-			return $out . '</div>';
289
-
290
-		} else {
291
-			return $out . " { ... }\n";
292
-		}
293
-	}
294
-
295
-
296
-	private static function dumpResource(&$var, $options, $level)
297
-	{
298
-		$type = get_resource_type($var);
299
-		$out = '<span class="tracy-dump-resource">' . Helpers::escapeHtml($type) . ' resource</span> '
300
-			. '<span class="tracy-dump-hash">#' . (int) $var . '</span>';
301
-		if (isset(self::$resources[$type])) {
302
-			$out = "<span class=\"tracy-toggle tracy-collapsed\">$out</span>\n<div class=\"tracy-collapsed\">";
303
-			foreach (call_user_func(self::$resources[$type], $var) as $k => $v) {
304
-				$out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
305
-					. '<span class="tracy-dump-key">' . Helpers::escapeHtml($k) . '</span> => ' . self::dumpVar($v, $options, $level + 1);
306
-			}
307
-			return $out . '</div>';
308
-		}
309
-		return "$out\n";
310
-	}
311
-
312
-
313
-	/**
314
-	 * @return mixed
315
-	 */
316
-	private static function toJson(&$var, $options, $level = 0)
317
-	{
318
-		if (is_bool($var) || $var === null || is_int($var)) {
319
-			return $var;
320
-
321
-		} elseif (is_float($var)) {
322
-			return is_finite($var)
323
-				? (strpos($tmp = json_encode($var), '.') ? $var : ['number' => "$tmp.0"])
324
-				: ['type' => (string) $var];
325
-
326
-		} elseif (is_string($var)) {
327
-			return self::encodeString($var, $options[self::TRUNCATE]);
328
-
329
-		} elseif (is_array($var)) {
330
-			static $marker;
331
-			if ($marker === null) {
332
-				$marker = uniqid("\x00", true);
333
-			}
334
-			if (isset($var[$marker]) || $level >= $options[self::DEPTH]) {
335
-				return [null];
336
-			}
337
-			$res = [];
338
-			$var[$marker] = true;
339
-			foreach ($var as $k => &$v) {
340
-				if ($k !== $marker) {
341
-					$hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]);
342
-					$k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"';
343
-					$res[] = [$k, $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1)];
344
-				}
345
-			}
346
-			unset($var[$marker]);
347
-			return $res;
348
-
349
-		} elseif (is_object($var)) {
350
-			$obj = &self::$liveStorage[spl_object_hash($var)];
351
-			if ($obj && $obj['level'] <= $level) {
352
-				return ['object' => $obj['id']];
353
-			}
354
-
355
-			$editorInfo = null;
356
-			if ($options[self::LOCATION] & self::LOCATION_CLASS) {
357
-				$rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var);
358
-				$editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine());
359
-				$editorInfo = $editor ? ['file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'url' => $editor] : null;
360
-			}
361
-			static $counter = 1;
362
-			$obj = $obj ?: [
363
-				'id' => self::$livePrefix . '0' . $counter++, // differentiate from resources
364
-				'name' => Helpers::getClass($var),
365
-				'editor' => $editorInfo,
366
-				'level' => $level,
367
-				'object' => $var,
368
-			];
369
-
370
-			if ($level < $options[self::DEPTH] || !$options[self::DEPTH]) {
371
-				$obj['level'] = $level;
372
-				$obj['items'] = [];
373
-
374
-				foreach (self::exportObject($var, $options[self::OBJECT_EXPORTERS], $options[self::DEBUGINFO]) as $k => $v) {
375
-					$vis = 0;
376
-					if (isset($k[0]) && $k[0] === "\x00") {
377
-						$vis = $k[1] === '*' ? 1 : 2;
378
-						$k = substr($k, strrpos($k, "\x00") + 1);
379
-					}
380
-					$hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]);
381
-					$k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"';
382
-					$obj['items'][] = [$k, $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1), $vis];
383
-				}
384
-			}
385
-			return ['object' => $obj['id']];
386
-
387
-		} elseif (is_resource($var)) {
388
-			$obj = &self::$liveStorage[(string) $var];
389
-			if (!$obj) {
390
-				$type = get_resource_type($var);
391
-				$obj = ['id' => self::$livePrefix . (int) $var, 'name' => $type . ' resource'];
392
-				if (isset(self::$resources[$type])) {
393
-					foreach (call_user_func(self::$resources[$type], $var) as $k => $v) {
394
-						$obj['items'][] = [$k, self::toJson($v, $options, $level + 1)];
395
-					}
396
-				}
397
-			}
398
-			return ['resource' => $obj['id']];
399
-
400
-		} else {
401
-			return ['type' => 'unknown type'];
402
-		}
403
-	}
404
-
405
-
406
-	/** @return array  */
407
-	public static function fetchLiveData()
408
-	{
409
-		$res = [];
410
-		foreach (self::$liveStorage as $obj) {
411
-			$id = $obj['id'];
412
-			unset($obj['level'], $obj['object'], $obj['id']);
413
-			$res[$id] = $obj;
414
-		}
415
-		self::$liveStorage = [];
416
-		return $res;
417
-	}
418
-
419
-
420
-	/**
421
-	 * @internal
422
-	 * @return string UTF-8
423
-	 */
424
-	public static function encodeString($s, $maxLength = null)
425
-	{
426
-		static $table;
427
-		if ($table === null) {
428
-			foreach (array_merge(range("\x00", "\x1F"), range("\x7F", "\xFF")) as $ch) {
429
-				$table[$ch] = '\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT);
430
-			}
431
-			$table['\\'] = '\\\\';
432
-			$table["\r"] = '\r';
433
-			$table["\n"] = '\n';
434
-			$table["\t"] = '\t';
435
-		}
436
-
437
-		if ($maxLength && strlen($s) > $maxLength) { // shortens to $maxLength in UTF-8 or longer
438
-			if (function_exists('mb_substr')) {
439
-				$s = mb_substr($tmp = $s, 0, $maxLength, 'UTF-8');
440
-				$shortened = $s !== $tmp;
441
-			} else {
442
-				$i = $len = 0;
443
-				$maxI = $maxLength * 4; // max UTF-8 length
444
-				do {
445
-					if (($s[$i] < "\x80" || $s[$i] >= "\xC0") && (++$len > $maxLength) || $i >= $maxI) {
446
-						$s = substr($s, 0, $i);
447
-						$shortened = true;
448
-						break;
449
-					}
450
-				} while (isset($s[++$i]));
451
-			}
452
-		}
453
-
454
-		if (preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $s) || preg_last_error()) { // is binary?
455
-			if ($maxLength && strlen($s) > $maxLength) {
456
-				$s = substr($s, 0, $maxLength);
457
-				$shortened = true;
458
-			}
459
-			$s = strtr($s, $table);
460
-		}
461
-
462
-		return $s . (empty($shortened) ? '' : ' ... ');
463
-	}
464
-
465
-
466
-	/**
467
-	 * @return array
468
-	 */
469
-	private static function exportObject($obj, array $exporters, $useDebugInfo)
470
-	{
471
-		foreach ($exporters as $type => $dumper) {
472
-			if (!$type || $obj instanceof $type) {
473
-				return call_user_func($dumper, $obj);
474
-			}
475
-		}
476
-
477
-		if ($useDebugInfo && method_exists($obj, '__debugInfo')) {
478
-			return $obj->__debugInfo();
479
-		}
480
-
481
-		return (array) $obj;
482
-	}
483
-
484
-
485
-	/**
486
-	 * @return array
487
-	 */
488
-	private static function exportClosure(\Closure $obj)
489
-	{
490
-		$rc = new \ReflectionFunction($obj);
491
-		$res = [];
492
-		foreach ($rc->getParameters() as $param) {
493
-			$res[] = '$' . $param->getName();
494
-		}
495
-		return [
496
-			'file' => $rc->getFileName(),
497
-			'line' => $rc->getStartLine(),
498
-			'variables' => $rc->getStaticVariables(),
499
-			'parameters' => implode(', ', $res),
500
-		];
501
-	}
502
-
503
-
504
-	/**
505
-	 * @return array
506
-	 */
507
-	private static function exportSplFileInfo(\SplFileInfo $obj)
508
-	{
509
-		return ['path' => $obj->getPathname()];
510
-	}
511
-
512
-
513
-	/**
514
-	 * @return array
515
-	 */
516
-	private static function exportSplObjectStorage(\SplObjectStorage $obj)
517
-	{
518
-		$res = [];
519
-		foreach (clone $obj as $item) {
520
-			$res[] = ['object' => $item, 'data' => $obj[$item]];
521
-		}
522
-		return $res;
523
-	}
524
-
525
-
526
-	/**
527
-	 * @return array
528
-	 */
529
-	private static function exportPhpIncompleteClass(\__PHP_Incomplete_Class $obj)
530
-	{
531
-		$info = ['className' => null, 'private' => [], 'protected' => [], 'public' => []];
532
-		foreach ((array) $obj as $name => $value) {
533
-			if ($name === '__PHP_Incomplete_Class_Name') {
534
-				$info['className'] = $value;
535
-			} elseif (preg_match('#^\x0\*\x0(.+)\z#', $name, $m)) {
536
-				$info['protected'][$m[1]] = $value;
537
-			} elseif (preg_match('#^\x0(.+)\x0(.+)\z#', $name, $m)) {
538
-				$info['private'][$m[1] . '::$' . $m[2]] = $value;
539
-			} else {
540
-				$info['public'][$name] = $value;
541
-			}
542
-		}
543
-		return $info;
544
-	}
545
-
546
-
547
-	/**
548
-	 * Finds the location where dump was called.
549
-	 * @return array|null [file, line, code]
550
-	 */
551
-	private static function findLocation()
552
-	{
553
-		foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) {
554
-			if (isset($item['class']) && $item['class'] === __CLASS__) {
555
-				$location = $item;
556
-				continue;
557
-			} elseif (isset($item['function'])) {
558
-				try {
559
-					$reflection = isset($item['class'])
560
-						? new \ReflectionMethod($item['class'], $item['function'])
561
-						: new \ReflectionFunction($item['function']);
562
-					if ($reflection->isInternal() || preg_match('#\s@tracySkipLocation\s#', (string) $reflection->getDocComment())) {
563
-						$location = $item;
564
-						continue;
565
-					}
566
-				} catch (\ReflectionException $e) {
567
-				}
568
-			}
569
-			break;
570
-		}
571
-
572
-		if (isset($location['file'], $location['line']) && is_file($location['file'])) {
573
-			$lines = file($location['file']);
574
-			$line = $lines[$location['line'] - 1];
575
-			return [
576
-				$location['file'],
577
-				$location['line'],
578
-				trim(preg_match('#\w*dump(er::\w+)?\(.*\)#i', $line, $m) ? $m[0] : $line),
579
-			];
580
-		}
581
-	}
582
-
583
-
584
-	/**
585
-	 * @return bool
586
-	 */
587
-	private static function detectColors()
588
-	{
589
-		return self::$terminalColors &&
590
-			(getenv('ConEmuANSI') === 'ON'
591
-			|| getenv('ANSICON') !== false
592
-			|| getenv('term') === 'xterm-256color'
593
-			|| (defined('STDOUT') && function_exists('posix_isatty') && posix_isatty(STDOUT)));
594
-	}
16
+    const
17
+        DEPTH = 'depth', // how many nested levels of array/object properties display (defaults to 4)
18
+        TRUNCATE = 'truncate', // how truncate long strings? (defaults to 150)
19
+        COLLAPSE = 'collapse', // collapse top array/object or how big are collapsed? (defaults to 14)
20
+        COLLAPSE_COUNT = 'collapsecount', // how big array/object are collapsed? (defaults to 7)
21
+        LOCATION = 'location', // show location string? (defaults to 0)
22
+        OBJECT_EXPORTERS = 'exporters', // custom exporters for objects (defaults to Dumper::$objectexporters)
23
+        LIVE = 'live', // will be rendered using JavaScript
24
+        DEBUGINFO = 'debuginfo', // use magic method __debugInfo if exists (defaults to false)
25
+        KEYS_TO_HIDE = 'keystohide'; // sensitive keys not displayed (defaults to [])
26
+
27
+    const
28
+        LOCATION_SOURCE = 0b0001, // shows where dump was called
29
+        LOCATION_LINK = 0b0010, // appends clickable anchor
30
+        LOCATION_CLASS = 0b0100; // shows where class is defined
31
+
32
+    const
33
+        HIDDEN_VALUE = '*****';
34
+
35
+    /** @var array */
36
+    public static $terminalColors = [
37
+        'bool' => '1;33',
38
+        'null' => '1;33',
39
+        'number' => '1;32',
40
+        'string' => '1;36',
41
+        'array' => '1;31',
42
+        'key' => '1;37',
43
+        'object' => '1;31',
44
+        'visibility' => '1;30',
45
+        'resource' => '1;37',
46
+        'indent' => '1;30',
47
+    ];
48
+
49
+    /** @var array */
50
+    public static $resources = [
51
+        'stream' => 'stream_get_meta_data',
52
+        'stream-context' => 'stream_context_get_options',
53
+        'curl' => 'curl_getinfo',
54
+    ];
55
+
56
+    /** @var array */
57
+    public static $objectExporters = [
58
+        'Closure' => 'Tracy\Dumper::exportClosure',
59
+        'SplFileInfo' => 'Tracy\Dumper::exportSplFileInfo',
60
+        'SplObjectStorage' => 'Tracy\Dumper::exportSplObjectStorage',
61
+        '__PHP_Incomplete_Class' => 'Tracy\Dumper::exportPhpIncompleteClass',
62
+    ];
63
+
64
+    /** @var string @internal */
65
+    public static $livePrefix;
66
+
67
+    /** @var array  */
68
+    private static $liveStorage = [];
69
+
70
+
71
+    /**
72
+     * Dumps variable to the output.
73
+     * @return mixed  variable
74
+     */
75
+    public static function dump($var, array $options = null)
76
+    {
77
+        if (PHP_SAPI !== 'cli' && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list()))) {
78
+            echo self::toHtml($var, $options);
79
+        } elseif (self::detectColors()) {
80
+            echo self::toTerminal($var, $options);
81
+        } else {
82
+            echo self::toText($var, $options);
83
+        }
84
+        return $var;
85
+    }
86
+
87
+
88
+    /**
89
+     * Dumps variable to HTML.
90
+     * @return string
91
+     */
92
+    public static function toHtml($var, array $options = null)
93
+    {
94
+        $options = (array) $options + [
95
+            self::DEPTH => 4,
96
+            self::TRUNCATE => 150,
97
+            self::COLLAPSE => 14,
98
+            self::COLLAPSE_COUNT => 7,
99
+            self::OBJECT_EXPORTERS => null,
100
+            self::DEBUGINFO => false,
101
+            self::KEYS_TO_HIDE => [],
102
+        ];
103
+        $loc = &$options[self::LOCATION];
104
+        $loc = $loc === true ? ~0 : (int) $loc;
105
+
106
+        $options[self::KEYS_TO_HIDE] = array_flip(array_map('strtolower', $options[self::KEYS_TO_HIDE]));
107
+        $options[self::OBJECT_EXPORTERS] = (array) $options[self::OBJECT_EXPORTERS] + self::$objectExporters;
108
+        uksort($options[self::OBJECT_EXPORTERS], function ($a, $b) {
109
+            return $b === '' || (class_exists($a, false) && is_subclass_of($a, $b)) ? -1 : 1;
110
+        });
111
+
112
+        $live = !empty($options[self::LIVE]) && $var && (is_array($var) || is_object($var) || is_resource($var));
113
+        list($file, $line, $code) = $loc ? self::findLocation() : null;
114
+        $locAttrs = $file && $loc & self::LOCATION_SOURCE ? Helpers::formatHtml(
115
+            ' title="%in file % on line %" data-tracy-href="%"', "$code\n", $file, $line, Helpers::editorUri($file, $line)
116
+        ) : null;
117
+
118
+        return '<pre class="tracy-dump' . ($live && $options[self::COLLAPSE] === true ? ' tracy-collapsed' : '') . '"'
119
+            . $locAttrs
120
+            . ($live ? " data-tracy-dump='" . json_encode(self::toJson($var, $options), JSON_HEX_APOS | JSON_HEX_AMP) . "'>" : '>')
121
+            . ($live ? '' : self::dumpVar($var, $options))
122
+            . ($file && $loc & self::LOCATION_LINK ? '<small>in ' . Helpers::editorLink($file, $line) . '</small>' : '')
123
+            . "</pre>\n";
124
+    }
125
+
126
+
127
+    /**
128
+     * Dumps variable to plain text.
129
+     * @return string
130
+     */
131
+    public static function toText($var, array $options = null)
132
+    {
133
+        return htmlspecialchars_decode(strip_tags(self::toHtml($var, $options)), ENT_QUOTES);
134
+    }
135
+
136
+
137
+    /**
138
+     * Dumps variable to x-terminal.
139
+     * @return string
140
+     */
141
+    public static function toTerminal($var, array $options = null)
142
+    {
143
+        return htmlspecialchars_decode(strip_tags(preg_replace_callback('#<span class="tracy-dump-(\w+)">|</span>#', function ($m) {
144
+            return "\033[" . (isset($m[1], self::$terminalColors[$m[1]]) ? self::$terminalColors[$m[1]] : '0') . 'm';
145
+        }, self::toHtml($var, $options))), ENT_QUOTES);
146
+    }
147
+
148
+
149
+    /**
150
+     * Internal toHtml() dump implementation.
151
+     * @param  mixed  $var
152
+     * @param  array  $options
153
+     * @param  int  $level  recursion level
154
+     * @return string
155
+     */
156
+    private static function dumpVar(&$var, array $options, $level = 0)
157
+    {
158
+        if (method_exists(__CLASS__, $m = 'dump' . gettype($var))) {
159
+            return self::$m($var, $options, $level);
160
+        } else {
161
+            return "<span>unknown type</span>\n";
162
+        }
163
+    }
164
+
165
+
166
+    private static function dumpNull()
167
+    {
168
+        return "<span class=\"tracy-dump-null\">null</span>\n";
169
+    }
170
+
171
+
172
+    private static function dumpBoolean(&$var)
173
+    {
174
+        return '<span class="tracy-dump-bool">' . ($var ? 'true' : 'false') . "</span>\n";
175
+    }
176
+
177
+
178
+    private static function dumpInteger(&$var)
179
+    {
180
+        return "<span class=\"tracy-dump-number\">$var</span>\n";
181
+    }
182
+
183
+
184
+    private static function dumpDouble(&$var)
185
+    {
186
+        $var = is_finite($var)
187
+            ? ($tmp = json_encode($var)) . (strpos($tmp, '.') === false ? '.0' : '')
188
+            : str_replace('.0', '', var_export($var, true)); // workaround for PHP 7.0.2
189
+        return "<span class=\"tracy-dump-number\">$var</span>\n";
190
+    }
191
+
192
+
193
+    private static function dumpString(&$var, $options)
194
+    {
195
+        return '<span class="tracy-dump-string">"'
196
+            . Helpers::escapeHtml(self::encodeString($var, $options[self::TRUNCATE]))
197
+            . '"</span>' . (strlen($var) > 1 ? ' (' . strlen($var) . ')' : '') . "\n";
198
+    }
199
+
200
+
201
+    private static function dumpArray(&$var, $options, $level)
202
+    {
203
+        static $marker;
204
+        if ($marker === null) {
205
+            $marker = uniqid("\x00", true);
206
+        }
207
+
208
+        $out = '<span class="tracy-dump-array">array</span> (';
209
+
210
+        if (empty($var)) {
211
+            return $out . ")\n";
212
+
213
+        } elseif (isset($var[$marker])) {
214
+            return $out . (count($var) - 1) . ") [ <i>RECURSION</i> ]\n";
215
+
216
+        } elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH]) {
217
+            $collapsed = $level ? count($var) >= $options[self::COLLAPSE_COUNT]
218
+                : (is_int($options[self::COLLAPSE]) ? count($var) >= $options[self::COLLAPSE] : $options[self::COLLAPSE]);
219
+            $out = '<span class="tracy-toggle' . ($collapsed ? ' tracy-collapsed' : '') . '">'
220
+                . $out . count($var) . ")</span>\n<div" . ($collapsed ? ' class="tracy-collapsed"' : '') . '>';
221
+            $var[$marker] = true;
222
+            foreach ($var as $k => &$v) {
223
+                if ($k !== $marker) {
224
+                    $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]) ? self::HIDDEN_VALUE : null;
225
+                    $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . Helpers::escapeHtml(self::encodeString($k, $options[self::TRUNCATE])) . '"';
226
+                    $out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
227
+                        . '<span class="tracy-dump-key">' . $k . '</span> => '
228
+                        . ($hide ? self::dumpString($hide, $options) : self::dumpVar($v, $options, $level + 1));
229
+                }
230
+            }
231
+            unset($var[$marker]);
232
+            return $out . '</div>';
233
+
234
+        } else {
235
+            return $out . count($var) . ") [ ... ]\n";
236
+        }
237
+    }
238
+
239
+
240
+    private static function dumpObject(&$var, $options, $level)
241
+    {
242
+        $fields = self::exportObject($var, $options[self::OBJECT_EXPORTERS], $options[self::DEBUGINFO]);
243
+
244
+        $editorAttributes = '';
245
+        if ($options[self::LOCATION] & self::LOCATION_CLASS) {
246
+            $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var);
247
+            $editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine());
248
+            if ($editor) {
249
+                $editorAttributes = Helpers::formatHtml(
250
+                    ' title="Declared in file % on line %" data-tracy-href="%"',
251
+                    $rc->getFileName(),
252
+                    $rc->getStartLine(),
253
+                    $editor
254
+                );
255
+            }
256
+        }
257
+        $out = '<span class="tracy-dump-object"' . $editorAttributes . '>'
258
+            . Helpers::escapeHtml(Helpers::getClass($var))
259
+            . '</span> <span class="tracy-dump-hash">#' . substr(md5(spl_object_hash($var)), 0, 4) . '</span>';
260
+
261
+        static $list = [];
262
+
263
+        if (empty($fields)) {
264
+            return $out . "\n";
265
+
266
+        } elseif (in_array($var, $list, true)) {
267
+            return $out . " { <i>RECURSION</i> }\n";
268
+
269
+        } elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH] || $var instanceof \Closure) {
270
+            $collapsed = $level ? count($fields) >= $options[self::COLLAPSE_COUNT]
271
+                : (is_int($options[self::COLLAPSE]) ? count($fields) >= $options[self::COLLAPSE] : $options[self::COLLAPSE]);
272
+            $out = '<span class="tracy-toggle' . ($collapsed ? ' tracy-collapsed' : '') . '">'
273
+                . $out . "</span>\n<div" . ($collapsed ? ' class="tracy-collapsed"' : '') . '>';
274
+            $list[] = $var;
275
+            foreach ($fields as $k => &$v) {
276
+                $vis = '';
277
+                if (isset($k[0]) && $k[0] === "\x00") {
278
+                    $vis = ' <span class="tracy-dump-visibility">' . ($k[1] === '*' ? 'protected' : 'private') . '</span>';
279
+                    $k = substr($k, strrpos($k, "\x00") + 1);
280
+                }
281
+                $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]) ? self::HIDDEN_VALUE : null;
282
+                $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . Helpers::escapeHtml(self::encodeString($k, $options[self::TRUNCATE])) . '"';
283
+                $out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
284
+                    . '<span class="tracy-dump-key">' . $k . "</span>$vis => "
285
+                    . ($hide ? self::dumpString($hide, $options) : self::dumpVar($v, $options, $level + 1));
286
+            }
287
+            array_pop($list);
288
+            return $out . '</div>';
289
+
290
+        } else {
291
+            return $out . " { ... }\n";
292
+        }
293
+    }
294
+
295
+
296
+    private static function dumpResource(&$var, $options, $level)
297
+    {
298
+        $type = get_resource_type($var);
299
+        $out = '<span class="tracy-dump-resource">' . Helpers::escapeHtml($type) . ' resource</span> '
300
+            . '<span class="tracy-dump-hash">#' . (int) $var . '</span>';
301
+        if (isset(self::$resources[$type])) {
302
+            $out = "<span class=\"tracy-toggle tracy-collapsed\">$out</span>\n<div class=\"tracy-collapsed\">";
303
+            foreach (call_user_func(self::$resources[$type], $var) as $k => $v) {
304
+                $out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
305
+                    . '<span class="tracy-dump-key">' . Helpers::escapeHtml($k) . '</span> => ' . self::dumpVar($v, $options, $level + 1);
306
+            }
307
+            return $out . '</div>';
308
+        }
309
+        return "$out\n";
310
+    }
311
+
312
+
313
+    /**
314
+     * @return mixed
315
+     */
316
+    private static function toJson(&$var, $options, $level = 0)
317
+    {
318
+        if (is_bool($var) || $var === null || is_int($var)) {
319
+            return $var;
320
+
321
+        } elseif (is_float($var)) {
322
+            return is_finite($var)
323
+                ? (strpos($tmp = json_encode($var), '.') ? $var : ['number' => "$tmp.0"])
324
+                : ['type' => (string) $var];
325
+
326
+        } elseif (is_string($var)) {
327
+            return self::encodeString($var, $options[self::TRUNCATE]);
328
+
329
+        } elseif (is_array($var)) {
330
+            static $marker;
331
+            if ($marker === null) {
332
+                $marker = uniqid("\x00", true);
333
+            }
334
+            if (isset($var[$marker]) || $level >= $options[self::DEPTH]) {
335
+                return [null];
336
+            }
337
+            $res = [];
338
+            $var[$marker] = true;
339
+            foreach ($var as $k => &$v) {
340
+                if ($k !== $marker) {
341
+                    $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]);
342
+                    $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"';
343
+                    $res[] = [$k, $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1)];
344
+                }
345
+            }
346
+            unset($var[$marker]);
347
+            return $res;
348
+
349
+        } elseif (is_object($var)) {
350
+            $obj = &self::$liveStorage[spl_object_hash($var)];
351
+            if ($obj && $obj['level'] <= $level) {
352
+                return ['object' => $obj['id']];
353
+            }
354
+
355
+            $editorInfo = null;
356
+            if ($options[self::LOCATION] & self::LOCATION_CLASS) {
357
+                $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var);
358
+                $editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine());
359
+                $editorInfo = $editor ? ['file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'url' => $editor] : null;
360
+            }
361
+            static $counter = 1;
362
+            $obj = $obj ?: [
363
+                'id' => self::$livePrefix . '0' . $counter++, // differentiate from resources
364
+                'name' => Helpers::getClass($var),
365
+                'editor' => $editorInfo,
366
+                'level' => $level,
367
+                'object' => $var,
368
+            ];
369
+
370
+            if ($level < $options[self::DEPTH] || !$options[self::DEPTH]) {
371
+                $obj['level'] = $level;
372
+                $obj['items'] = [];
373
+
374
+                foreach (self::exportObject($var, $options[self::OBJECT_EXPORTERS], $options[self::DEBUGINFO]) as $k => $v) {
375
+                    $vis = 0;
376
+                    if (isset($k[0]) && $k[0] === "\x00") {
377
+                        $vis = $k[1] === '*' ? 1 : 2;
378
+                        $k = substr($k, strrpos($k, "\x00") + 1);
379
+                    }
380
+                    $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]);
381
+                    $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"';
382
+                    $obj['items'][] = [$k, $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1), $vis];
383
+                }
384
+            }
385
+            return ['object' => $obj['id']];
386
+
387
+        } elseif (is_resource($var)) {
388
+            $obj = &self::$liveStorage[(string) $var];
389
+            if (!$obj) {
390
+                $type = get_resource_type($var);
391
+                $obj = ['id' => self::$livePrefix . (int) $var, 'name' => $type . ' resource'];
392
+                if (isset(self::$resources[$type])) {
393
+                    foreach (call_user_func(self::$resources[$type], $var) as $k => $v) {
394
+                        $obj['items'][] = [$k, self::toJson($v, $options, $level + 1)];
395
+                    }
396
+                }
397
+            }
398
+            return ['resource' => $obj['id']];
399
+
400
+        } else {
401
+            return ['type' => 'unknown type'];
402
+        }
403
+    }
404
+
405
+
406
+    /** @return array  */
407
+    public static function fetchLiveData()
408
+    {
409
+        $res = [];
410
+        foreach (self::$liveStorage as $obj) {
411
+            $id = $obj['id'];
412
+            unset($obj['level'], $obj['object'], $obj['id']);
413
+            $res[$id] = $obj;
414
+        }
415
+        self::$liveStorage = [];
416
+        return $res;
417
+    }
418
+
419
+
420
+    /**
421
+     * @internal
422
+     * @return string UTF-8
423
+     */
424
+    public static function encodeString($s, $maxLength = null)
425
+    {
426
+        static $table;
427
+        if ($table === null) {
428
+            foreach (array_merge(range("\x00", "\x1F"), range("\x7F", "\xFF")) as $ch) {
429
+                $table[$ch] = '\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT);
430
+            }
431
+            $table['\\'] = '\\\\';
432
+            $table["\r"] = '\r';
433
+            $table["\n"] = '\n';
434
+            $table["\t"] = '\t';
435
+        }
436
+
437
+        if ($maxLength && strlen($s) > $maxLength) { // shortens to $maxLength in UTF-8 or longer
438
+            if (function_exists('mb_substr')) {
439
+                $s = mb_substr($tmp = $s, 0, $maxLength, 'UTF-8');
440
+                $shortened = $s !== $tmp;
441
+            } else {
442
+                $i = $len = 0;
443
+                $maxI = $maxLength * 4; // max UTF-8 length
444
+                do {
445
+                    if (($s[$i] < "\x80" || $s[$i] >= "\xC0") && (++$len > $maxLength) || $i >= $maxI) {
446
+                        $s = substr($s, 0, $i);
447
+                        $shortened = true;
448
+                        break;
449
+                    }
450
+                } while (isset($s[++$i]));
451
+            }
452
+        }
453
+
454
+        if (preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $s) || preg_last_error()) { // is binary?
455
+            if ($maxLength && strlen($s) > $maxLength) {
456
+                $s = substr($s, 0, $maxLength);
457
+                $shortened = true;
458
+            }
459
+            $s = strtr($s, $table);
460
+        }
461
+
462
+        return $s . (empty($shortened) ? '' : ' ... ');
463
+    }
464
+
465
+
466
+    /**
467
+     * @return array
468
+     */
469
+    private static function exportObject($obj, array $exporters, $useDebugInfo)
470
+    {
471
+        foreach ($exporters as $type => $dumper) {
472
+            if (!$type || $obj instanceof $type) {
473
+                return call_user_func($dumper, $obj);
474
+            }
475
+        }
476
+
477
+        if ($useDebugInfo && method_exists($obj, '__debugInfo')) {
478
+            return $obj->__debugInfo();
479
+        }
480
+
481
+        return (array) $obj;
482
+    }
483
+
484
+
485
+    /**
486
+     * @return array
487
+     */
488
+    private static function exportClosure(\Closure $obj)
489
+    {
490
+        $rc = new \ReflectionFunction($obj);
491
+        $res = [];
492
+        foreach ($rc->getParameters() as $param) {
493
+            $res[] = '$' . $param->getName();
494
+        }
495
+        return [
496
+            'file' => $rc->getFileName(),
497
+            'line' => $rc->getStartLine(),
498
+            'variables' => $rc->getStaticVariables(),
499
+            'parameters' => implode(', ', $res),
500
+        ];
501
+    }
502
+
503
+
504
+    /**
505
+     * @return array
506
+     */
507
+    private static function exportSplFileInfo(\SplFileInfo $obj)
508
+    {
509
+        return ['path' => $obj->getPathname()];
510
+    }
511
+
512
+
513
+    /**
514
+     * @return array
515
+     */
516
+    private static function exportSplObjectStorage(\SplObjectStorage $obj)
517
+    {
518
+        $res = [];
519
+        foreach (clone $obj as $item) {
520
+            $res[] = ['object' => $item, 'data' => $obj[$item]];
521
+        }
522
+        return $res;
523
+    }
524
+
525
+
526
+    /**
527
+     * @return array
528
+     */
529
+    private static function exportPhpIncompleteClass(\__PHP_Incomplete_Class $obj)
530
+    {
531
+        $info = ['className' => null, 'private' => [], 'protected' => [], 'public' => []];
532
+        foreach ((array) $obj as $name => $value) {
533
+            if ($name === '__PHP_Incomplete_Class_Name') {
534
+                $info['className'] = $value;
535
+            } elseif (preg_match('#^\x0\*\x0(.+)\z#', $name, $m)) {
536
+                $info['protected'][$m[1]] = $value;
537
+            } elseif (preg_match('#^\x0(.+)\x0(.+)\z#', $name, $m)) {
538
+                $info['private'][$m[1] . '::$' . $m[2]] = $value;
539
+            } else {
540
+                $info['public'][$name] = $value;
541
+            }
542
+        }
543
+        return $info;
544
+    }
545
+
546
+
547
+    /**
548
+     * Finds the location where dump was called.
549
+     * @return array|null [file, line, code]
550
+     */
551
+    private static function findLocation()
552
+    {
553
+        foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) {
554
+            if (isset($item['class']) && $item['class'] === __CLASS__) {
555
+                $location = $item;
556
+                continue;
557
+            } elseif (isset($item['function'])) {
558
+                try {
559
+                    $reflection = isset($item['class'])
560
+                        ? new \ReflectionMethod($item['class'], $item['function'])
561
+                        : new \ReflectionFunction($item['function']);
562
+                    if ($reflection->isInternal() || preg_match('#\s@tracySkipLocation\s#', (string) $reflection->getDocComment())) {
563
+                        $location = $item;
564
+                        continue;
565
+                    }
566
+                } catch (\ReflectionException $e) {
567
+                }
568
+            }
569
+            break;
570
+        }
571
+
572
+        if (isset($location['file'], $location['line']) && is_file($location['file'])) {
573
+            $lines = file($location['file']);
574
+            $line = $lines[$location['line'] - 1];
575
+            return [
576
+                $location['file'],
577
+                $location['line'],
578
+                trim(preg_match('#\w*dump(er::\w+)?\(.*\)#i', $line, $m) ? $m[0] : $line),
579
+            ];
580
+        }
581
+    }
582
+
583
+
584
+    /**
585
+     * @return bool
586
+     */
587
+    private static function detectColors()
588
+    {
589
+        return self::$terminalColors &&
590
+            (getenv('ConEmuANSI') === 'ON'
591
+            || getenv('ANSICON') !== false
592
+            || getenv('term') === 'xterm-256color'
593
+            || (defined('STDOUT') && function_exists('posix_isatty') && posix_isatty(STDOUT)));
594
+    }
595 595
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/Bar.php 1 patch
Indentation   +234 added lines, -234 removed lines patch added patch discarded remove patch
@@ -13,233 +13,233 @@  discard block
 block discarded – undo
13 13
  */
14 14
 class Bar
15 15
 {
16
-	/** @var IBarPanel[] */
17
-	private $panels = [];
18
-
19
-	/** @var bool  initialized by dispatchAssets() */
20
-	private $useSession = false;
21
-
22
-	/** @var string|NULL  generated by renderLoader() */
23
-	private $contentId;
24
-
25
-
26
-	/**
27
-	 * Add custom panel.
28
-	 * @param  IBarPanel  $panel
29
-	 * @param  string  $id
30
-	 * @return static
31
-	 */
32
-	public function addPanel(IBarPanel $panel, $id = null)
33
-	{
34
-		if ($id === null) {
35
-			$c = 0;
36
-			do {
37
-				$id = get_class($panel) . ($c++ ? "-$c" : '');
38
-			} while (isset($this->panels[$id]));
39
-		}
40
-		$this->panels[$id] = $panel;
41
-		return $this;
42
-	}
43
-
44
-
45
-	/**
46
-	 * Returns panel with given id
47
-	 * @param  string  $id
48
-	 * @return IBarPanel|null
49
-	 */
50
-	public function getPanel($id)
51
-	{
52
-		return isset($this->panels[$id]) ? $this->panels[$id] : null;
53
-	}
54
-
55
-
56
-	/**
57
-	 * Renders loading <script>
58
-	 * @return void
59
-	 */
60
-	public function renderLoader()
61
-	{
62
-		if (!$this->useSession) {
63
-			throw new \LogicException('Start session before Tracy is enabled.');
64
-		}
65
-		$contentId = $this->contentId = $this->contentId ?: substr(md5(uniqid('', true)), 0, 10);
66
-		$nonce = Helpers::getNonce();
67
-		$async = true;
68
-		require __DIR__ . '/assets/Bar/loader.phtml';
69
-	}
70
-
71
-
72
-	/**
73
-	 * Renders debug bar.
74
-	 * @return void
75
-	 */
76
-	public function render()
77
-	{
78
-		$useSession = $this->useSession && session_status() === PHP_SESSION_ACTIVE;
79
-		$redirectQueue = &$_SESSION['_tracy']['redirect'];
80
-
81
-		foreach (['bar', 'redirect', 'bluescreen'] as $key) {
82
-			$queue = &$_SESSION['_tracy'][$key];
83
-			$queue = array_slice((array) $queue, -10, null, true);
84
-			$queue = array_filter($queue, function ($item) {
85
-				return isset($item['time']) && $item['time'] > time() - 60;
86
-			});
87
-		}
88
-
89
-		$rows = [];
90
-
91
-		if (Helpers::isAjax()) {
92
-			if ($useSession) {
93
-				$rows[] = (object) ['type' => 'ajax', 'panels' => $this->renderPanels('-ajax')];
94
-				$contentId = $_SERVER['HTTP_X_TRACY_AJAX'] . '-ajax';
95
-				$_SESSION['_tracy']['bar'][$contentId] = ['content' => self::renderHtmlRows($rows), 'dumps' => Dumper::fetchLiveData(), 'time' => time()];
96
-			}
97
-
98
-		} elseif (preg_match('#^Location:#im', implode("\n", headers_list()))) { // redirect
99
-			if ($useSession) {
100
-				Dumper::fetchLiveData();
101
-				Dumper::$livePrefix = count($redirectQueue) . 'p';
102
-				$redirectQueue[] = [
103
-					'panels' => $this->renderPanels('-r' . count($redirectQueue)),
104
-					'dumps' => Dumper::fetchLiveData(),
105
-					'time' => time(),
106
-				];
107
-			}
108
-
109
-		} elseif (Helpers::isHtmlMode()) {
110
-			$rows[] = (object) ['type' => 'main', 'panels' => $this->renderPanels()];
111
-			$dumps = Dumper::fetchLiveData();
112
-			foreach (array_reverse((array) $redirectQueue) as $info) {
113
-				$rows[] = (object) ['type' => 'redirect', 'panels' => $info['panels']];
114
-				$dumps += $info['dumps'];
115
-			}
116
-			$redirectQueue = null;
117
-			$content = self::renderHtmlRows($rows);
118
-
119
-			if ($this->contentId) {
120
-				$_SESSION['_tracy']['bar'][$this->contentId] = ['content' => $content, 'dumps' => $dumps, 'time' => time()];
121
-			} else {
122
-				$contentId = substr(md5(uniqid('', true)), 0, 10);
123
-				$nonce = Helpers::getNonce();
124
-				$async = false;
125
-				require __DIR__ . '/assets/Bar/loader.phtml';
126
-			}
127
-		}
128
-	}
129
-
130
-
131
-	/**
132
-	 * @return string
133
-	 */
134
-	private static function renderHtmlRows(array $rows)
135
-	{
136
-		ob_start(function () {});
137
-		require __DIR__ . '/assets/Bar/panels.phtml';
138
-		require __DIR__ . '/assets/Bar/bar.phtml';
139
-		return Helpers::fixEncoding(ob_get_clean());
140
-	}
141
-
142
-
143
-	/**
144
-	 * @return array
145
-	 */
146
-	private function renderPanels($suffix = null)
147
-	{
148
-		set_error_handler(function ($severity, $message, $file, $line) {
149
-			if (error_reporting() & $severity) {
150
-				throw new \ErrorException($message, 0, $severity, $file, $line);
151
-			}
152
-		});
153
-
154
-		$obLevel = ob_get_level();
155
-		$panels = [];
156
-
157
-		foreach ($this->panels as $id => $panel) {
158
-			$idHtml = preg_replace('#[^a-z0-9]+#i', '-', $id) . $suffix;
159
-			try {
160
-				$tab = (string) $panel->getTab();
161
-				$panelHtml = $tab ? (string) $panel->getPanel() : null;
162
-				if ($tab && $panel instanceof \Nette\Diagnostics\IBarPanel) {
163
-					$e = new \Exception('Support for Nette\Diagnostics\IBarPanel is deprecated');
164
-				}
165
-
166
-			} catch (\Exception $e) {
167
-			} catch (\Throwable $e) {
168
-			}
169
-			if (isset($e)) {
170
-				while (ob_get_level() > $obLevel) { // restore ob-level if broken
171
-					ob_end_clean();
172
-				}
173
-				$idHtml = "error-$idHtml";
174
-				$tab = "Error in $id";
175
-				$panelHtml = "<h1>Error: $id</h1><div class='tracy-inner'>" . nl2br(Helpers::escapeHtml($e)) . '</div>';
176
-				unset($e);
177
-			}
178
-			$panels[] = (object) ['id' => $idHtml, 'tab' => $tab, 'panel' => $panelHtml];
179
-		}
180
-
181
-		restore_error_handler();
182
-		return $panels;
183
-	}
184
-
185
-
186
-	/**
187
-	 * Renders debug bar assets.
188
-	 * @return bool
189
-	 */
190
-	public function dispatchAssets()
191
-	{
192
-		$asset = isset($_GET['_tracy_bar']) ? $_GET['_tracy_bar'] : null;
193
-		if ($asset === 'js') {
194
-			header('Content-Type: application/javascript');
195
-			header('Cache-Control: max-age=864000');
196
-			header_remove('Pragma');
197
-			header_remove('Set-Cookie');
198
-			$this->renderAssets();
199
-			return true;
200
-		}
201
-
202
-		$this->useSession = session_status() === PHP_SESSION_ACTIVE;
203
-
204
-		if ($this->useSession && Helpers::isAjax()) {
205
-			header('X-Tracy-Ajax: 1'); // session must be already locked
206
-		}
207
-
208
-		if ($this->useSession && $asset && preg_match('#^content(-ajax)?\.(\w+)$#', $asset, $m)) {
209
-			$session = &$_SESSION['_tracy']['bar'][$m[2] . $m[1]];
210
-			header('Content-Type: application/javascript');
211
-			header('Cache-Control: max-age=60');
212
-			header_remove('Set-Cookie');
213
-			if (!$m[1]) {
214
-				$this->renderAssets();
215
-			}
216
-			if ($session) {
217
-				$method = $m[1] ? 'loadAjax' : 'init';
218
-				echo "Tracy.Debug.$method(", json_encode($session['content']), ', ', json_encode($session['dumps']), ');';
219
-				$session = null;
220
-			}
221
-			$session = &$_SESSION['_tracy']['bluescreen'][$m[2]];
222
-			if ($session) {
223
-				echo 'Tracy.BlueScreen.loadAjax(', json_encode($session['content']), ', ', json_encode($session['dumps']), ');';
224
-				$session = null;
225
-			}
226
-			return true;
227
-		}
228
-
229
-		return false;
230
-	}
231
-
232
-
233
-	private function renderAssets()
234
-	{
235
-		$css = array_map('file_get_contents', array_merge([
236
-			__DIR__ . '/assets/Bar/bar.css',
237
-			__DIR__ . '/assets/Toggle/toggle.css',
238
-			__DIR__ . '/assets/Dumper/dumper.css',
239
-			__DIR__ . '/assets/BlueScreen/bluescreen.css',
240
-		], Debugger::$customCssFiles));
241
-
242
-		echo
16
+    /** @var IBarPanel[] */
17
+    private $panels = [];
18
+
19
+    /** @var bool  initialized by dispatchAssets() */
20
+    private $useSession = false;
21
+
22
+    /** @var string|NULL  generated by renderLoader() */
23
+    private $contentId;
24
+
25
+
26
+    /**
27
+     * Add custom panel.
28
+     * @param  IBarPanel  $panel
29
+     * @param  string  $id
30
+     * @return static
31
+     */
32
+    public function addPanel(IBarPanel $panel, $id = null)
33
+    {
34
+        if ($id === null) {
35
+            $c = 0;
36
+            do {
37
+                $id = get_class($panel) . ($c++ ? "-$c" : '');
38
+            } while (isset($this->panels[$id]));
39
+        }
40
+        $this->panels[$id] = $panel;
41
+        return $this;
42
+    }
43
+
44
+
45
+    /**
46
+     * Returns panel with given id
47
+     * @param  string  $id
48
+     * @return IBarPanel|null
49
+     */
50
+    public function getPanel($id)
51
+    {
52
+        return isset($this->panels[$id]) ? $this->panels[$id] : null;
53
+    }
54
+
55
+
56
+    /**
57
+     * Renders loading <script>
58
+     * @return void
59
+     */
60
+    public function renderLoader()
61
+    {
62
+        if (!$this->useSession) {
63
+            throw new \LogicException('Start session before Tracy is enabled.');
64
+        }
65
+        $contentId = $this->contentId = $this->contentId ?: substr(md5(uniqid('', true)), 0, 10);
66
+        $nonce = Helpers::getNonce();
67
+        $async = true;
68
+        require __DIR__ . '/assets/Bar/loader.phtml';
69
+    }
70
+
71
+
72
+    /**
73
+     * Renders debug bar.
74
+     * @return void
75
+     */
76
+    public function render()
77
+    {
78
+        $useSession = $this->useSession && session_status() === PHP_SESSION_ACTIVE;
79
+        $redirectQueue = &$_SESSION['_tracy']['redirect'];
80
+
81
+        foreach (['bar', 'redirect', 'bluescreen'] as $key) {
82
+            $queue = &$_SESSION['_tracy'][$key];
83
+            $queue = array_slice((array) $queue, -10, null, true);
84
+            $queue = array_filter($queue, function ($item) {
85
+                return isset($item['time']) && $item['time'] > time() - 60;
86
+            });
87
+        }
88
+
89
+        $rows = [];
90
+
91
+        if (Helpers::isAjax()) {
92
+            if ($useSession) {
93
+                $rows[] = (object) ['type' => 'ajax', 'panels' => $this->renderPanels('-ajax')];
94
+                $contentId = $_SERVER['HTTP_X_TRACY_AJAX'] . '-ajax';
95
+                $_SESSION['_tracy']['bar'][$contentId] = ['content' => self::renderHtmlRows($rows), 'dumps' => Dumper::fetchLiveData(), 'time' => time()];
96
+            }
97
+
98
+        } elseif (preg_match('#^Location:#im', implode("\n", headers_list()))) { // redirect
99
+            if ($useSession) {
100
+                Dumper::fetchLiveData();
101
+                Dumper::$livePrefix = count($redirectQueue) . 'p';
102
+                $redirectQueue[] = [
103
+                    'panels' => $this->renderPanels('-r' . count($redirectQueue)),
104
+                    'dumps' => Dumper::fetchLiveData(),
105
+                    'time' => time(),
106
+                ];
107
+            }
108
+
109
+        } elseif (Helpers::isHtmlMode()) {
110
+            $rows[] = (object) ['type' => 'main', 'panels' => $this->renderPanels()];
111
+            $dumps = Dumper::fetchLiveData();
112
+            foreach (array_reverse((array) $redirectQueue) as $info) {
113
+                $rows[] = (object) ['type' => 'redirect', 'panels' => $info['panels']];
114
+                $dumps += $info['dumps'];
115
+            }
116
+            $redirectQueue = null;
117
+            $content = self::renderHtmlRows($rows);
118
+
119
+            if ($this->contentId) {
120
+                $_SESSION['_tracy']['bar'][$this->contentId] = ['content' => $content, 'dumps' => $dumps, 'time' => time()];
121
+            } else {
122
+                $contentId = substr(md5(uniqid('', true)), 0, 10);
123
+                $nonce = Helpers::getNonce();
124
+                $async = false;
125
+                require __DIR__ . '/assets/Bar/loader.phtml';
126
+            }
127
+        }
128
+    }
129
+
130
+
131
+    /**
132
+     * @return string
133
+     */
134
+    private static function renderHtmlRows(array $rows)
135
+    {
136
+        ob_start(function () {});
137
+        require __DIR__ . '/assets/Bar/panels.phtml';
138
+        require __DIR__ . '/assets/Bar/bar.phtml';
139
+        return Helpers::fixEncoding(ob_get_clean());
140
+    }
141
+
142
+
143
+    /**
144
+     * @return array
145
+     */
146
+    private function renderPanels($suffix = null)
147
+    {
148
+        set_error_handler(function ($severity, $message, $file, $line) {
149
+            if (error_reporting() & $severity) {
150
+                throw new \ErrorException($message, 0, $severity, $file, $line);
151
+            }
152
+        });
153
+
154
+        $obLevel = ob_get_level();
155
+        $panels = [];
156
+
157
+        foreach ($this->panels as $id => $panel) {
158
+            $idHtml = preg_replace('#[^a-z0-9]+#i', '-', $id) . $suffix;
159
+            try {
160
+                $tab = (string) $panel->getTab();
161
+                $panelHtml = $tab ? (string) $panel->getPanel() : null;
162
+                if ($tab && $panel instanceof \Nette\Diagnostics\IBarPanel) {
163
+                    $e = new \Exception('Support for Nette\Diagnostics\IBarPanel is deprecated');
164
+                }
165
+
166
+            } catch (\Exception $e) {
167
+            } catch (\Throwable $e) {
168
+            }
169
+            if (isset($e)) {
170
+                while (ob_get_level() > $obLevel) { // restore ob-level if broken
171
+                    ob_end_clean();
172
+                }
173
+                $idHtml = "error-$idHtml";
174
+                $tab = "Error in $id";
175
+                $panelHtml = "<h1>Error: $id</h1><div class='tracy-inner'>" . nl2br(Helpers::escapeHtml($e)) . '</div>';
176
+                unset($e);
177
+            }
178
+            $panels[] = (object) ['id' => $idHtml, 'tab' => $tab, 'panel' => $panelHtml];
179
+        }
180
+
181
+        restore_error_handler();
182
+        return $panels;
183
+    }
184
+
185
+
186
+    /**
187
+     * Renders debug bar assets.
188
+     * @return bool
189
+     */
190
+    public function dispatchAssets()
191
+    {
192
+        $asset = isset($_GET['_tracy_bar']) ? $_GET['_tracy_bar'] : null;
193
+        if ($asset === 'js') {
194
+            header('Content-Type: application/javascript');
195
+            header('Cache-Control: max-age=864000');
196
+            header_remove('Pragma');
197
+            header_remove('Set-Cookie');
198
+            $this->renderAssets();
199
+            return true;
200
+        }
201
+
202
+        $this->useSession = session_status() === PHP_SESSION_ACTIVE;
203
+
204
+        if ($this->useSession && Helpers::isAjax()) {
205
+            header('X-Tracy-Ajax: 1'); // session must be already locked
206
+        }
207
+
208
+        if ($this->useSession && $asset && preg_match('#^content(-ajax)?\.(\w+)$#', $asset, $m)) {
209
+            $session = &$_SESSION['_tracy']['bar'][$m[2] . $m[1]];
210
+            header('Content-Type: application/javascript');
211
+            header('Cache-Control: max-age=60');
212
+            header_remove('Set-Cookie');
213
+            if (!$m[1]) {
214
+                $this->renderAssets();
215
+            }
216
+            if ($session) {
217
+                $method = $m[1] ? 'loadAjax' : 'init';
218
+                echo "Tracy.Debug.$method(", json_encode($session['content']), ', ', json_encode($session['dumps']), ');';
219
+                $session = null;
220
+            }
221
+            $session = &$_SESSION['_tracy']['bluescreen'][$m[2]];
222
+            if ($session) {
223
+                echo 'Tracy.BlueScreen.loadAjax(', json_encode($session['content']), ', ', json_encode($session['dumps']), ');';
224
+                $session = null;
225
+            }
226
+            return true;
227
+        }
228
+
229
+        return false;
230
+    }
231
+
232
+
233
+    private function renderAssets()
234
+    {
235
+        $css = array_map('file_get_contents', array_merge([
236
+            __DIR__ . '/assets/Bar/bar.css',
237
+            __DIR__ . '/assets/Toggle/toggle.css',
238
+            __DIR__ . '/assets/Dumper/dumper.css',
239
+            __DIR__ . '/assets/BlueScreen/bluescreen.css',
240
+        ], Debugger::$customCssFiles));
241
+
242
+        echo
243 243
 "(function(){
244 244
 	var el = document.createElement('style');
245 245
 	el.setAttribute('nonce', document.currentScript.getAttribute('nonce') || document.currentScript.nonce);
@@ -248,11 +248,11 @@  discard block
 block discarded – undo
248 248
 	document.head.appendChild(el);})
249 249
 ();\n";
250 250
 
251
-		array_map('readfile', array_merge([
252
-			__DIR__ . '/assets/Bar/bar.js',
253
-			__DIR__ . '/assets/Toggle/toggle.js',
254
-			__DIR__ . '/assets/Dumper/dumper.js',
255
-			__DIR__ . '/assets/BlueScreen/bluescreen.js',
256
-		], Debugger::$customJsFiles));
257
-	}
251
+        array_map('readfile', array_merge([
252
+            __DIR__ . '/assets/Bar/bar.js',
253
+            __DIR__ . '/assets/Toggle/toggle.js',
254
+            __DIR__ . '/assets/Dumper/dumper.js',
255
+            __DIR__ . '/assets/BlueScreen/bluescreen.js',
256
+        ], Debugger::$customJsFiles));
257
+    }
258 258
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/OutputDebugger.php 1 patch
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -13,66 +13,66 @@
 block discarded – undo
13 13
  */
14 14
 class OutputDebugger
15 15
 {
16
-	const BOM = "\xEF\xBB\xBF";
16
+    const BOM = "\xEF\xBB\xBF";
17 17
 
18
-	/** @var array of [file, line, output, stack] */
19
-	private $list = [];
18
+    /** @var array of [file, line, output, stack] */
19
+    private $list = [];
20 20
 
21 21
 
22
-	public static function enable()
23
-	{
24
-		$me = new static;
25
-		$me->start();
26
-	}
22
+    public static function enable()
23
+    {
24
+        $me = new static;
25
+        $me->start();
26
+    }
27 27
 
28 28
 
29
-	public function start()
30
-	{
31
-		foreach (get_included_files() as $file) {
32
-			if (fread(fopen($file, 'r'), 3) === self::BOM) {
33
-				$this->list[] = [$file, 1, self::BOM];
34
-			}
35
-		}
36
-		ob_start([$this, 'handler'], 1);
37
-	}
29
+    public function start()
30
+    {
31
+        foreach (get_included_files() as $file) {
32
+            if (fread(fopen($file, 'r'), 3) === self::BOM) {
33
+                $this->list[] = [$file, 1, self::BOM];
34
+            }
35
+        }
36
+        ob_start([$this, 'handler'], 1);
37
+    }
38 38
 
39 39
 
40
-	/** @internal */
41
-	public function handler($s, $phase)
42
-	{
43
-		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
44
-		if (isset($trace[0]['file'], $trace[0]['line'])) {
45
-			$stack = $trace;
46
-			unset($stack[0]['line'], $stack[0]['args']);
47
-			$i = count($this->list);
48
-			if ($i && $this->list[$i - 1][3] === $stack) {
49
-				$this->list[$i - 1][2] .= $s;
50
-			} else {
51
-				$this->list[] = [$trace[0]['file'], $trace[0]['line'], $s, $stack];
52
-			}
53
-		}
54
-		if ($phase === PHP_OUTPUT_HANDLER_FINAL) {
55
-			return $this->renderHtml();
56
-		}
57
-	}
40
+    /** @internal */
41
+    public function handler($s, $phase)
42
+    {
43
+        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
44
+        if (isset($trace[0]['file'], $trace[0]['line'])) {
45
+            $stack = $trace;
46
+            unset($stack[0]['line'], $stack[0]['args']);
47
+            $i = count($this->list);
48
+            if ($i && $this->list[$i - 1][3] === $stack) {
49
+                $this->list[$i - 1][2] .= $s;
50
+            } else {
51
+                $this->list[] = [$trace[0]['file'], $trace[0]['line'], $s, $stack];
52
+            }
53
+        }
54
+        if ($phase === PHP_OUTPUT_HANDLER_FINAL) {
55
+            return $this->renderHtml();
56
+        }
57
+    }
58 58
 
59 59
 
60
-	private function renderHtml()
61
-	{
62
-		$res = '<style>code, pre {white-space:nowrap} a {text-decoration:none} pre {color:gray;display:inline} big {color:red}</style><code>';
63
-		foreach ($this->list as $item) {
64
-			$stack = [];
65
-			foreach (array_slice($item[3], 1) as $t) {
66
-				$t += ['class' => '', 'type' => '', 'function' => ''];
67
-				$stack[] = "$t[class]$t[type]$t[function]()"
68
-					. (isset($t['file'], $t['line']) ? ' in ' . basename($t['file']) . ":$t[line]" : '');
69
-			}
60
+    private function renderHtml()
61
+    {
62
+        $res = '<style>code, pre {white-space:nowrap} a {text-decoration:none} pre {color:gray;display:inline} big {color:red}</style><code>';
63
+        foreach ($this->list as $item) {
64
+            $stack = [];
65
+            foreach (array_slice($item[3], 1) as $t) {
66
+                $t += ['class' => '', 'type' => '', 'function' => ''];
67
+                $stack[] = "$t[class]$t[type]$t[function]()"
68
+                    . (isset($t['file'], $t['line']) ? ' in ' . basename($t['file']) . ":$t[line]" : '');
69
+            }
70 70
 
71
-			$res .= '<span title="' . Helpers::escapeHtml(implode("\n", $stack)) . '">'
72
-				. Helpers::editorLink($item[0], $item[1]) . ' '
73
-				. str_replace(self::BOM, '<big>BOM</big>', Dumper::toHtml($item[2]))
74
-				. "</span><br>\n";
75
-		}
76
-		return $res . '</code>';
77
-	}
71
+            $res .= '<span title="' . Helpers::escapeHtml(implode("\n", $stack)) . '">'
72
+                . Helpers::editorLink($item[0], $item[1]) . ' '
73
+                . str_replace(self::BOM, '<big>BOM</big>', Dumper::toHtml($item[2]))
74
+                . "</span><br>\n";
75
+        }
76
+        return $res . '</code>';
77
+    }
78 78
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/Logger.php 1 patch
Indentation   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -13,197 +13,197 @@
 block discarded – undo
13 13
  */
14 14
 class Logger implements ILogger
15 15
 {
16
-	/** @var string|null name of the directory where errors should be logged */
17
-	public $directory;
18
-
19
-	/** @var string|array|null email or emails to which send error notifications */
20
-	public $email;
21
-
22
-	/** @var string|null sender of email notifications */
23
-	public $fromEmail;
24
-
25
-	/** @var mixed interval for sending email is 2 days */
26
-	public $emailSnooze = '2 days';
27
-
28
-	/** @var callable handler for sending emails */
29
-	public $mailer;
30
-
31
-	/** @var BlueScreen|null */
32
-	private $blueScreen;
33
-
34
-
35
-	/**
36
-	 * @param  string|null  $directory
37
-	 * @param  string|array|null  $email
38
-	 */
39
-	public function __construct($directory, $email = null, BlueScreen $blueScreen = null)
40
-	{
41
-		$this->directory = $directory;
42
-		$this->email = $email;
43
-		$this->blueScreen = $blueScreen;
44
-		$this->mailer = [$this, 'defaultMailer'];
45
-	}
46
-
47
-
48
-	/**
49
-	 * Logs message or exception to file and sends email notification.
50
-	 * @param  mixed  $message
51
-	 * @param  string  $priority  one of constant ILogger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email)
52
-	 * @return string|null logged error filename
53
-	 */
54
-	public function log($message, $priority = self::INFO)
55
-	{
56
-		if (!$this->directory) {
57
-			throw new \LogicException('Logging directory is not specified.');
58
-		} elseif (!is_dir($this->directory)) {
59
-			throw new \RuntimeException("Logging directory '$this->directory' is not found or is not directory.");
60
-		}
61
-
62
-		$exceptionFile = $message instanceof \Exception || $message instanceof \Throwable
63
-			? $this->getExceptionFile($message)
64
-			: null;
65
-		$line = static::formatLogLine($message, $exceptionFile);
66
-		$file = $this->directory . '/' . strtolower($priority ?: self::INFO) . '.log';
67
-
68
-		if (!@file_put_contents($file, $line . PHP_EOL, FILE_APPEND | LOCK_EX)) { // @ is escalated to exception
69
-			throw new \RuntimeException("Unable to write to log file '$file'. Is directory writable?");
70
-		}
71
-
72
-		if ($exceptionFile) {
73
-			$this->logException($message, $exceptionFile);
74
-		}
75
-
76
-		if (in_array($priority, [self::ERROR, self::EXCEPTION, self::CRITICAL], true)) {
77
-			$this->sendEmail($message);
78
-		}
79
-
80
-		return $exceptionFile;
81
-	}
82
-
83
-
84
-	/**
85
-	 * @param  mixed  $message
86
-	 * @return string
87
-	 */
88
-	public static function formatMessage($message)
89
-	{
90
-		if ($message instanceof \Exception || $message instanceof \Throwable) {
91
-			while ($message) {
92
-				$tmp[] = ($message instanceof \ErrorException
93
-					? Helpers::errorTypeToString($message->getSeverity()) . ': ' . $message->getMessage()
94
-					: Helpers::getClass($message) . ': ' . $message->getMessage() . ($message->getCode() ? ' #' . $message->getCode() : '')
95
-				) . ' in ' . $message->getFile() . ':' . $message->getLine();
96
-				$message = $message->getPrevious();
97
-			}
98
-			$message = implode("\ncaused by ", $tmp);
99
-
100
-		} elseif (!is_string($message)) {
101
-			$message = Dumper::toText($message);
102
-		}
103
-
104
-		return trim($message);
105
-	}
106
-
107
-
108
-	/**
109
-	 * @param  mixed  $message
110
-	 * @return string
111
-	 */
112
-	public static function formatLogLine($message, $exceptionFile = null)
113
-	{
114
-		return implode(' ', [
115
-			@date('[Y-m-d H-i-s]'), // @ timezone may not be set
116
-			preg_replace('#\s*\r?\n\s*#', ' ', static::formatMessage($message)),
117
-			' @  ' . Helpers::getSource(),
118
-			$exceptionFile ? ' @@  ' . basename($exceptionFile) : null,
119
-		]);
120
-	}
121
-
122
-
123
-	/**
124
-	 * @param  \Exception|\Throwable  $exception
125
-	 * @return string
126
-	 */
127
-	public function getExceptionFile($exception)
128
-	{
129
-		while ($exception) {
130
-			$data[] = [
131
-				get_class($exception), $exception->getMessage(), $exception->getCode(), $exception->getFile(), $exception->getLine(),
132
-				array_map(function ($item) { unset($item['args']); return $item; }, $exception->getTrace()),
133
-			];
134
-			$exception = $exception->getPrevious();
135
-		}
136
-		$hash = substr(md5(serialize($data)), 0, 10);
137
-		$dir = strtr($this->directory . '/', '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR);
138
-		foreach (new \DirectoryIterator($this->directory) as $file) {
139
-			if (strpos($file->getBasename(), $hash)) {
140
-				return $dir . $file;
141
-			}
142
-		}
143
-		return $dir . 'exception--' . @date('Y-m-d--H-i') . "--$hash.html"; // @ timezone may not be set
144
-	}
145
-
146
-
147
-	/**
148
-	 * Logs exception to the file if file doesn't exist.
149
-	 * @param  \Exception|\Throwable  $exception
150
-	 * @return string logged error filename
151
-	 */
152
-	protected function logException($exception, $file = null)
153
-	{
154
-		$file = $file ?: $this->getExceptionFile($exception);
155
-		$bs = $this->blueScreen ?: new BlueScreen;
156
-		$bs->renderToFile($exception, $file);
157
-		return $file;
158
-	}
159
-
160
-
161
-	/**
162
-	 * @param  mixed  $message
163
-	 * @return void
164
-	 */
165
-	protected function sendEmail($message)
166
-	{
167
-		$snooze = is_numeric($this->emailSnooze)
168
-			? $this->emailSnooze
169
-			: @strtotime($this->emailSnooze) - time(); // @ timezone may not be set
170
-
171
-		if (
172
-			$this->email
173
-			&& $this->mailer
174
-			&& @filemtime($this->directory . '/email-sent') + $snooze < time() // @ file may not exist
175
-			&& @file_put_contents($this->directory . '/email-sent', 'sent') // @ file may not be writable
176
-		) {
177
-			call_user_func($this->mailer, $message, implode(', ', (array) $this->email));
178
-		}
179
-	}
180
-
181
-
182
-	/**
183
-	 * Default mailer.
184
-	 * @param  mixed  $message
185
-	 * @param  string  $email
186
-	 * @return void
187
-	 * @internal
188
-	 */
189
-	public function defaultMailer($message, $email)
190
-	{
191
-		$host = preg_replace('#[^\w.-]+#', '', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n'));
192
-		$parts = str_replace(
193
-			["\r\n", "\n"],
194
-			["\n", PHP_EOL],
195
-			[
196
-				'headers' => implode("\n", [
197
-					'From: ' . ($this->fromEmail ?: "noreply@$host"),
198
-					'X-Mailer: Tracy',
199
-					'Content-Type: text/plain; charset=UTF-8',
200
-					'Content-Transfer-Encoding: 8bit',
201
-				]) . "\n",
202
-				'subject' => "PHP: An error occurred on the server $host",
203
-				'body' => static::formatMessage($message) . "\n\nsource: " . Helpers::getSource(),
204
-			]
205
-		);
206
-
207
-		mail($email, $parts['subject'], $parts['body'], $parts['headers']);
208
-	}
16
+    /** @var string|null name of the directory where errors should be logged */
17
+    public $directory;
18
+
19
+    /** @var string|array|null email or emails to which send error notifications */
20
+    public $email;
21
+
22
+    /** @var string|null sender of email notifications */
23
+    public $fromEmail;
24
+
25
+    /** @var mixed interval for sending email is 2 days */
26
+    public $emailSnooze = '2 days';
27
+
28
+    /** @var callable handler for sending emails */
29
+    public $mailer;
30
+
31
+    /** @var BlueScreen|null */
32
+    private $blueScreen;
33
+
34
+
35
+    /**
36
+     * @param  string|null  $directory
37
+     * @param  string|array|null  $email
38
+     */
39
+    public function __construct($directory, $email = null, BlueScreen $blueScreen = null)
40
+    {
41
+        $this->directory = $directory;
42
+        $this->email = $email;
43
+        $this->blueScreen = $blueScreen;
44
+        $this->mailer = [$this, 'defaultMailer'];
45
+    }
46
+
47
+
48
+    /**
49
+     * Logs message or exception to file and sends email notification.
50
+     * @param  mixed  $message
51
+     * @param  string  $priority  one of constant ILogger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email)
52
+     * @return string|null logged error filename
53
+     */
54
+    public function log($message, $priority = self::INFO)
55
+    {
56
+        if (!$this->directory) {
57
+            throw new \LogicException('Logging directory is not specified.');
58
+        } elseif (!is_dir($this->directory)) {
59
+            throw new \RuntimeException("Logging directory '$this->directory' is not found or is not directory.");
60
+        }
61
+
62
+        $exceptionFile = $message instanceof \Exception || $message instanceof \Throwable
63
+            ? $this->getExceptionFile($message)
64
+            : null;
65
+        $line = static::formatLogLine($message, $exceptionFile);
66
+        $file = $this->directory . '/' . strtolower($priority ?: self::INFO) . '.log';
67
+
68
+        if (!@file_put_contents($file, $line . PHP_EOL, FILE_APPEND | LOCK_EX)) { // @ is escalated to exception
69
+            throw new \RuntimeException("Unable to write to log file '$file'. Is directory writable?");
70
+        }
71
+
72
+        if ($exceptionFile) {
73
+            $this->logException($message, $exceptionFile);
74
+        }
75
+
76
+        if (in_array($priority, [self::ERROR, self::EXCEPTION, self::CRITICAL], true)) {
77
+            $this->sendEmail($message);
78
+        }
79
+
80
+        return $exceptionFile;
81
+    }
82
+
83
+
84
+    /**
85
+     * @param  mixed  $message
86
+     * @return string
87
+     */
88
+    public static function formatMessage($message)
89
+    {
90
+        if ($message instanceof \Exception || $message instanceof \Throwable) {
91
+            while ($message) {
92
+                $tmp[] = ($message instanceof \ErrorException
93
+                    ? Helpers::errorTypeToString($message->getSeverity()) . ': ' . $message->getMessage()
94
+                    : Helpers::getClass($message) . ': ' . $message->getMessage() . ($message->getCode() ? ' #' . $message->getCode() : '')
95
+                ) . ' in ' . $message->getFile() . ':' . $message->getLine();
96
+                $message = $message->getPrevious();
97
+            }
98
+            $message = implode("\ncaused by ", $tmp);
99
+
100
+        } elseif (!is_string($message)) {
101
+            $message = Dumper::toText($message);
102
+        }
103
+
104
+        return trim($message);
105
+    }
106
+
107
+
108
+    /**
109
+     * @param  mixed  $message
110
+     * @return string
111
+     */
112
+    public static function formatLogLine($message, $exceptionFile = null)
113
+    {
114
+        return implode(' ', [
115
+            @date('[Y-m-d H-i-s]'), // @ timezone may not be set
116
+            preg_replace('#\s*\r?\n\s*#', ' ', static::formatMessage($message)),
117
+            ' @  ' . Helpers::getSource(),
118
+            $exceptionFile ? ' @@  ' . basename($exceptionFile) : null,
119
+        ]);
120
+    }
121
+
122
+
123
+    /**
124
+     * @param  \Exception|\Throwable  $exception
125
+     * @return string
126
+     */
127
+    public function getExceptionFile($exception)
128
+    {
129
+        while ($exception) {
130
+            $data[] = [
131
+                get_class($exception), $exception->getMessage(), $exception->getCode(), $exception->getFile(), $exception->getLine(),
132
+                array_map(function ($item) { unset($item['args']); return $item; }, $exception->getTrace()),
133
+            ];
134
+            $exception = $exception->getPrevious();
135
+        }
136
+        $hash = substr(md5(serialize($data)), 0, 10);
137
+        $dir = strtr($this->directory . '/', '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR);
138
+        foreach (new \DirectoryIterator($this->directory) as $file) {
139
+            if (strpos($file->getBasename(), $hash)) {
140
+                return $dir . $file;
141
+            }
142
+        }
143
+        return $dir . 'exception--' . @date('Y-m-d--H-i') . "--$hash.html"; // @ timezone may not be set
144
+    }
145
+
146
+
147
+    /**
148
+     * Logs exception to the file if file doesn't exist.
149
+     * @param  \Exception|\Throwable  $exception
150
+     * @return string logged error filename
151
+     */
152
+    protected function logException($exception, $file = null)
153
+    {
154
+        $file = $file ?: $this->getExceptionFile($exception);
155
+        $bs = $this->blueScreen ?: new BlueScreen;
156
+        $bs->renderToFile($exception, $file);
157
+        return $file;
158
+    }
159
+
160
+
161
+    /**
162
+     * @param  mixed  $message
163
+     * @return void
164
+     */
165
+    protected function sendEmail($message)
166
+    {
167
+        $snooze = is_numeric($this->emailSnooze)
168
+            ? $this->emailSnooze
169
+            : @strtotime($this->emailSnooze) - time(); // @ timezone may not be set
170
+
171
+        if (
172
+            $this->email
173
+            && $this->mailer
174
+            && @filemtime($this->directory . '/email-sent') + $snooze < time() // @ file may not exist
175
+            && @file_put_contents($this->directory . '/email-sent', 'sent') // @ file may not be writable
176
+        ) {
177
+            call_user_func($this->mailer, $message, implode(', ', (array) $this->email));
178
+        }
179
+    }
180
+
181
+
182
+    /**
183
+     * Default mailer.
184
+     * @param  mixed  $message
185
+     * @param  string  $email
186
+     * @return void
187
+     * @internal
188
+     */
189
+    public function defaultMailer($message, $email)
190
+    {
191
+        $host = preg_replace('#[^\w.-]+#', '', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n'));
192
+        $parts = str_replace(
193
+            ["\r\n", "\n"],
194
+            ["\n", PHP_EOL],
195
+            [
196
+                'headers' => implode("\n", [
197
+                    'From: ' . ($this->fromEmail ?: "noreply@$host"),
198
+                    'X-Mailer: Tracy',
199
+                    'Content-Type: text/plain; charset=UTF-8',
200
+                    'Content-Transfer-Encoding: 8bit',
201
+                ]) . "\n",
202
+                'subject' => "PHP: An error occurred on the server $host",
203
+                'body' => static::formatMessage($message) . "\n\nsource: " . Helpers::getSource(),
204
+            ]
205
+        );
206
+
207
+        mail($email, $parts['subject'], $parts['body'], $parts['headers']);
208
+    }
209 209
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/BlueScreen.php 1 patch
Indentation   +343 added lines, -343 removed lines patch added patch discarded remove patch
@@ -13,347 +13,347 @@
 block discarded – undo
13 13
  */
14 14
 class BlueScreen
15 15
 {
16
-	/** @var string[] */
17
-	public $info = [];
18
-
19
-	/** @var string[] paths to be collapsed in stack trace (e.g. core libraries) */
20
-	public $collapsePaths = [];
21
-
22
-	/** @var int  */
23
-	public $maxDepth = 3;
24
-
25
-	/** @var int  */
26
-	public $maxLength = 150;
27
-
28
-	/** @var string[] */
29
-	public $keysToHide = ['password', 'passwd', 'pass', 'pwd', 'creditcard', 'credit card', 'cc', 'pin'];
30
-
31
-	/** @var callable[] */
32
-	private $panels = [];
33
-
34
-	/** @var callable[] functions that returns action for exceptions */
35
-	private $actions = [];
36
-
37
-
38
-	public function __construct()
39
-	{
40
-		$this->collapsePaths[] = preg_match('#(.+/vendor)/tracy/tracy/src/Tracy$#', strtr(__DIR__, '\\', '/'), $m)
41
-			? $m[1]
42
-			: __DIR__;
43
-	}
44
-
45
-
46
-	/**
47
-	 * Add custom panel.
48
-	 * @param  callable  $panel
49
-	 * @return static
50
-	 */
51
-	public function addPanel($panel)
52
-	{
53
-		if (!in_array($panel, $this->panels, true)) {
54
-			$this->panels[] = $panel;
55
-		}
56
-		return $this;
57
-	}
58
-
59
-
60
-	/**
61
-	 * Add action.
62
-	 * @param  callable  $action
63
-	 * @return static
64
-	 */
65
-	public function addAction($action)
66
-	{
67
-		$this->actions[] = $action;
68
-		return $this;
69
-	}
70
-
71
-
72
-	/**
73
-	 * Renders blue screen.
74
-	 * @param  \Exception|\Throwable  $exception
75
-	 * @return void
76
-	 */
77
-	public function render($exception)
78
-	{
79
-		if (Helpers::isAjax() && session_status() === PHP_SESSION_ACTIVE) {
80
-			ob_start(function () {});
81
-			$this->renderTemplate($exception, __DIR__ . '/assets/BlueScreen/content.phtml');
82
-			$contentId = $_SERVER['HTTP_X_TRACY_AJAX'];
83
-			$_SESSION['_tracy']['bluescreen'][$contentId] = ['content' => ob_get_clean(), 'dumps' => Dumper::fetchLiveData(), 'time' => time()];
84
-
85
-		} else {
86
-			$this->renderTemplate($exception, __DIR__ . '/assets/BlueScreen/page.phtml');
87
-		}
88
-	}
89
-
90
-
91
-	/**
92
-	 * Renders blue screen to file (if file exists, it will not be overwritten).
93
-	 * @param  \Exception|\Throwable  $exception
94
-	 * @param  string  $file file path
95
-	 * @return void
96
-	 */
97
-	public function renderToFile($exception, $file)
98
-	{
99
-		if ($handle = @fopen($file, 'x')) {
100
-			ob_start(); // double buffer prevents sending HTTP headers in some PHP
101
-			ob_start(function ($buffer) use ($handle) { fwrite($handle, $buffer); }, 4096);
102
-			$this->renderTemplate($exception, __DIR__ . '/assets/BlueScreen/page.phtml', false);
103
-			ob_end_flush();
104
-			ob_end_clean();
105
-			fclose($handle);
106
-		}
107
-	}
108
-
109
-
110
-	private function renderTemplate($exception, $template, $toScreen = true)
111
-	{
112
-		$messageHtml = preg_replace(
113
-			'#\'\S[^\']*\S\'|"\S[^"]*\S"#U',
114
-			'<i>$0</i>',
115
-			htmlspecialchars((string) $exception->getMessage(), ENT_SUBSTITUTE, 'UTF-8')
116
-		);
117
-		$info = array_filter($this->info);
118
-		$source = Helpers::getSource();
119
-		$sourceIsUrl = preg_match('#^https?://#', $source);
120
-		$title = $exception instanceof \ErrorException
121
-			? Helpers::errorTypeToString($exception->getSeverity())
122
-			: Helpers::getClass($exception);
123
-		$lastError = $exception instanceof \ErrorException || $exception instanceof \Error ? null : error_get_last();
124
-
125
-		$keysToHide = array_flip(array_map('strtolower', $this->keysToHide));
126
-		$dump = function ($v, $k = null) use ($keysToHide) {
127
-			if (is_string($k) && isset($keysToHide[strtolower($k)])) {
128
-				$v = Dumper::HIDDEN_VALUE;
129
-			}
130
-			return Dumper::toHtml($v, [
131
-				Dumper::DEPTH => $this->maxDepth,
132
-				Dumper::TRUNCATE => $this->maxLength,
133
-				Dumper::LIVE => true,
134
-				Dumper::LOCATION => Dumper::LOCATION_CLASS,
135
-				Dumper::KEYS_TO_HIDE => $this->keysToHide,
136
-			]);
137
-		};
138
-		$css = array_map('file_get_contents', array_merge([
139
-			__DIR__ . '/assets/BlueScreen/bluescreen.css',
140
-		], Debugger::$customCssFiles));
141
-		$css = preg_replace('#\s+#u', ' ', implode($css));
142
-
143
-		$nonce = $toScreen ? Helpers::getNonce() : null;
144
-		$actions = $toScreen ? $this->renderActions($exception) : [];
145
-
146
-		require $template;
147
-	}
148
-
149
-
150
-	/**
151
-	 * @return \stdClass[]
152
-	 */
153
-	private function renderPanels($ex)
154
-	{
155
-		$obLevel = ob_get_level();
156
-		$res = [];
157
-		foreach ($this->panels as $callback) {
158
-			try {
159
-				$panel = call_user_func($callback, $ex);
160
-				if (empty($panel['tab']) || empty($panel['panel'])) {
161
-					continue;
162
-				}
163
-				$res[] = (object) $panel;
164
-				continue;
165
-			} catch (\Exception $e) {
166
-			} catch (\Throwable $e) {
167
-			}
168
-			while (ob_get_level() > $obLevel) { // restore ob-level if broken
169
-				ob_end_clean();
170
-			}
171
-			is_callable($callback, true, $name);
172
-			$res[] = (object) [
173
-				'tab' => "Error in panel $name",
174
-				'panel' => nl2br(Helpers::escapeHtml($e)),
175
-			];
176
-		}
177
-		return $res;
178
-	}
179
-
180
-
181
-	/**
182
-	 * @return array[]
183
-	 */
184
-	private function renderActions($ex)
185
-	{
186
-		$actions = [];
187
-		foreach ($this->actions as $callback) {
188
-			$action = call_user_func($callback, $ex);
189
-			if (!empty($action['link']) && !empty($action['label'])) {
190
-				$actions[] = $action;
191
-			}
192
-		}
193
-
194
-		if (property_exists($ex, 'tracyAction') && !empty($ex->tracyAction['link']) && !empty($ex->tracyAction['label'])) {
195
-			$actions[] = $ex->tracyAction;
196
-		}
197
-
198
-		if (preg_match('# ([\'"])(\w{3,}(?:\\\\\w{3,})+)\\1#i', $ex->getMessage(), $m)) {
199
-			$class = $m[2];
200
-			if (
201
-				!class_exists($class) && !interface_exists($class) && !trait_exists($class)
202
-				&& ($file = Helpers::guessClassFile($class)) && !is_file($file)
203
-			) {
204
-				$actions[] = [
205
-					'link' => Helpers::editorUri($file, 1, 'create'),
206
-					'label' => 'create class',
207
-				];
208
-			}
209
-		}
210
-
211
-		if (preg_match('# ([\'"])((?:/|[a-z]:[/\\\\])\w[^\'"]+\.\w{2,5})\\1#i', $ex->getMessage(), $m)) {
212
-			$file = $m[2];
213
-			$actions[] = [
214
-				'link' => Helpers::editorUri($file, 1, $label = is_file($file) ? 'open' : 'create'),
215
-				'label' => $label . ' file',
216
-			];
217
-		}
218
-
219
-		$query = ($ex instanceof \ErrorException ? '' : Helpers::getClass($ex) . ' ')
220
-			. preg_replace('#\'.*\'|".*"#Us', '', $ex->getMessage());
221
-		$actions[] = [
222
-			'link' => 'https://www.google.com/search?sourceid=tracy&q=' . urlencode($query),
223
-			'label' => 'search',
224
-			'external' => true,
225
-		];
226
-
227
-		if (
228
-			$ex instanceof \ErrorException
229
-			&& !empty($ex->skippable)
230
-			&& preg_match('#^https?://#', $source = Helpers::getSource())
231
-		) {
232
-			$actions[] = [
233
-				'link' => $source . (strpos($source, '?') ? '&' : '?') . '_tracy_skip_error',
234
-				'label' => 'skip error',
235
-			];
236
-		}
237
-		return $actions;
238
-	}
239
-
240
-
241
-	/**
242
-	 * Returns syntax highlighted source code.
243
-	 * @param  string  $file
244
-	 * @param  int  $line
245
-	 * @param  int  $lines
246
-	 * @return string|null
247
-	 */
248
-	public static function highlightFile($file, $line, $lines = 15, array $vars = null)
249
-	{
250
-		$source = @file_get_contents($file); // @ file may not exist
251
-		if ($source) {
252
-			$source = static::highlightPhp($source, $line, $lines, $vars);
253
-			if ($editor = Helpers::editorUri($file, $line)) {
254
-				$source = substr_replace($source, ' data-tracy-href="' . Helpers::escapeHtml($editor) . '"', 4, 0);
255
-			}
256
-			return $source;
257
-		}
258
-	}
259
-
260
-
261
-	/**
262
-	 * Returns syntax highlighted source code.
263
-	 * @param  string  $source
264
-	 * @param  int  $line
265
-	 * @param  int  $lines
266
-	 * @return string
267
-	 */
268
-	public static function highlightPhp($source, $line, $lines = 15, array $vars = null)
269
-	{
270
-		if (function_exists('ini_set')) {
271
-			ini_set('highlight.comment', '#998; font-style: italic');
272
-			ini_set('highlight.default', '#000');
273
-			ini_set('highlight.html', '#06B');
274
-			ini_set('highlight.keyword', '#D24; font-weight: bold');
275
-			ini_set('highlight.string', '#080');
276
-		}
277
-
278
-		$source = str_replace(["\r\n", "\r"], "\n", $source);
279
-		$source = explode("\n", highlight_string($source, true));
280
-		$out = $source[0]; // <code><span color=highlight.html>
281
-		$source = str_replace('<br />', "\n", $source[1]);
282
-		$out .= static::highlightLine($source, $line, $lines);
283
-
284
-		if ($vars) {
285
-			$out = preg_replace_callback('#">\$(\w+)(&nbsp;)?</span>#', function ($m) use ($vars) {
286
-				return array_key_exists($m[1], $vars)
287
-					? '" title="'
288
-						. str_replace('"', '&quot;', trim(strip_tags(Dumper::toHtml($vars[$m[1]], [Dumper::DEPTH => 1]))))
289
-						. $m[0]
290
-					: $m[0];
291
-			}, $out);
292
-		}
293
-
294
-		$out = str_replace('&nbsp;', ' ', $out);
295
-		return "<pre class='code'><div>$out</div></pre>";
296
-	}
297
-
298
-
299
-	/**
300
-	 * Returns highlighted line in HTML code.
301
-	 * @return string
302
-	 */
303
-	public static function highlightLine($html, $line, $lines = 15)
304
-	{
305
-		$source = explode("\n", "\n" . str_replace("\r\n", "\n", $html));
306
-		$out = '';
307
-		$spans = 1;
308
-		$start = $i = max(1, min($line, count($source) - 1) - (int) floor($lines * 2 / 3));
309
-		while (--$i >= 1) { // find last highlighted block
310
-			if (preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) {
311
-				if ($m[1] !== '</span>') {
312
-					$spans++;
313
-					$out .= $m[1];
314
-				}
315
-				break;
316
-			}
317
-		}
318
-
319
-		$source = array_slice($source, $start, $lines, true);
320
-		end($source);
321
-		$numWidth = strlen((string) key($source));
322
-
323
-		foreach ($source as $n => $s) {
324
-			$spans += substr_count($s, '<span') - substr_count($s, '</span');
325
-			$s = str_replace(["\r", "\n"], ['', ''], $s);
326
-			preg_match_all('#<[^>]+>#', $s, $tags);
327
-			if ($n == $line) {
328
-				$out .= sprintf(
329
-					"<span class='highlight'>%{$numWidth}s:    %s\n</span>%s",
330
-					$n,
331
-					strip_tags($s),
332
-					implode('', $tags[0])
333
-				);
334
-			} else {
335
-				$out .= sprintf("<span class='line'>%{$numWidth}s:</span>    %s\n", $n, $s);
336
-			}
337
-		}
338
-		$out .= str_repeat('</span>', $spans) . '</code>';
339
-		return $out;
340
-	}
341
-
342
-
343
-	/**
344
-	 * Should a file be collapsed in stack trace?
345
-	 * @param  string  $file
346
-	 * @return bool
347
-	 */
348
-	public function isCollapsed($file)
349
-	{
350
-		$file = strtr($file, '\\', '/') . '/';
351
-		foreach ($this->collapsePaths as $path) {
352
-			$path = strtr($path, '\\', '/') . '/';
353
-			if (strncmp($file, $path, strlen($path)) === 0) {
354
-				return true;
355
-			}
356
-		}
357
-		return false;
358
-	}
16
+    /** @var string[] */
17
+    public $info = [];
18
+
19
+    /** @var string[] paths to be collapsed in stack trace (e.g. core libraries) */
20
+    public $collapsePaths = [];
21
+
22
+    /** @var int  */
23
+    public $maxDepth = 3;
24
+
25
+    /** @var int  */
26
+    public $maxLength = 150;
27
+
28
+    /** @var string[] */
29
+    public $keysToHide = ['password', 'passwd', 'pass', 'pwd', 'creditcard', 'credit card', 'cc', 'pin'];
30
+
31
+    /** @var callable[] */
32
+    private $panels = [];
33
+
34
+    /** @var callable[] functions that returns action for exceptions */
35
+    private $actions = [];
36
+
37
+
38
+    public function __construct()
39
+    {
40
+        $this->collapsePaths[] = preg_match('#(.+/vendor)/tracy/tracy/src/Tracy$#', strtr(__DIR__, '\\', '/'), $m)
41
+            ? $m[1]
42
+            : __DIR__;
43
+    }
44
+
45
+
46
+    /**
47
+     * Add custom panel.
48
+     * @param  callable  $panel
49
+     * @return static
50
+     */
51
+    public function addPanel($panel)
52
+    {
53
+        if (!in_array($panel, $this->panels, true)) {
54
+            $this->panels[] = $panel;
55
+        }
56
+        return $this;
57
+    }
58
+
59
+
60
+    /**
61
+     * Add action.
62
+     * @param  callable  $action
63
+     * @return static
64
+     */
65
+    public function addAction($action)
66
+    {
67
+        $this->actions[] = $action;
68
+        return $this;
69
+    }
70
+
71
+
72
+    /**
73
+     * Renders blue screen.
74
+     * @param  \Exception|\Throwable  $exception
75
+     * @return void
76
+     */
77
+    public function render($exception)
78
+    {
79
+        if (Helpers::isAjax() && session_status() === PHP_SESSION_ACTIVE) {
80
+            ob_start(function () {});
81
+            $this->renderTemplate($exception, __DIR__ . '/assets/BlueScreen/content.phtml');
82
+            $contentId = $_SERVER['HTTP_X_TRACY_AJAX'];
83
+            $_SESSION['_tracy']['bluescreen'][$contentId] = ['content' => ob_get_clean(), 'dumps' => Dumper::fetchLiveData(), 'time' => time()];
84
+
85
+        } else {
86
+            $this->renderTemplate($exception, __DIR__ . '/assets/BlueScreen/page.phtml');
87
+        }
88
+    }
89
+
90
+
91
+    /**
92
+     * Renders blue screen to file (if file exists, it will not be overwritten).
93
+     * @param  \Exception|\Throwable  $exception
94
+     * @param  string  $file file path
95
+     * @return void
96
+     */
97
+    public function renderToFile($exception, $file)
98
+    {
99
+        if ($handle = @fopen($file, 'x')) {
100
+            ob_start(); // double buffer prevents sending HTTP headers in some PHP
101
+            ob_start(function ($buffer) use ($handle) { fwrite($handle, $buffer); }, 4096);
102
+            $this->renderTemplate($exception, __DIR__ . '/assets/BlueScreen/page.phtml', false);
103
+            ob_end_flush();
104
+            ob_end_clean();
105
+            fclose($handle);
106
+        }
107
+    }
108
+
109
+
110
+    private function renderTemplate($exception, $template, $toScreen = true)
111
+    {
112
+        $messageHtml = preg_replace(
113
+            '#\'\S[^\']*\S\'|"\S[^"]*\S"#U',
114
+            '<i>$0</i>',
115
+            htmlspecialchars((string) $exception->getMessage(), ENT_SUBSTITUTE, 'UTF-8')
116
+        );
117
+        $info = array_filter($this->info);
118
+        $source = Helpers::getSource();
119
+        $sourceIsUrl = preg_match('#^https?://#', $source);
120
+        $title = $exception instanceof \ErrorException
121
+            ? Helpers::errorTypeToString($exception->getSeverity())
122
+            : Helpers::getClass($exception);
123
+        $lastError = $exception instanceof \ErrorException || $exception instanceof \Error ? null : error_get_last();
124
+
125
+        $keysToHide = array_flip(array_map('strtolower', $this->keysToHide));
126
+        $dump = function ($v, $k = null) use ($keysToHide) {
127
+            if (is_string($k) && isset($keysToHide[strtolower($k)])) {
128
+                $v = Dumper::HIDDEN_VALUE;
129
+            }
130
+            return Dumper::toHtml($v, [
131
+                Dumper::DEPTH => $this->maxDepth,
132
+                Dumper::TRUNCATE => $this->maxLength,
133
+                Dumper::LIVE => true,
134
+                Dumper::LOCATION => Dumper::LOCATION_CLASS,
135
+                Dumper::KEYS_TO_HIDE => $this->keysToHide,
136
+            ]);
137
+        };
138
+        $css = array_map('file_get_contents', array_merge([
139
+            __DIR__ . '/assets/BlueScreen/bluescreen.css',
140
+        ], Debugger::$customCssFiles));
141
+        $css = preg_replace('#\s+#u', ' ', implode($css));
142
+
143
+        $nonce = $toScreen ? Helpers::getNonce() : null;
144
+        $actions = $toScreen ? $this->renderActions($exception) : [];
145
+
146
+        require $template;
147
+    }
148
+
149
+
150
+    /**
151
+     * @return \stdClass[]
152
+     */
153
+    private function renderPanels($ex)
154
+    {
155
+        $obLevel = ob_get_level();
156
+        $res = [];
157
+        foreach ($this->panels as $callback) {
158
+            try {
159
+                $panel = call_user_func($callback, $ex);
160
+                if (empty($panel['tab']) || empty($panel['panel'])) {
161
+                    continue;
162
+                }
163
+                $res[] = (object) $panel;
164
+                continue;
165
+            } catch (\Exception $e) {
166
+            } catch (\Throwable $e) {
167
+            }
168
+            while (ob_get_level() > $obLevel) { // restore ob-level if broken
169
+                ob_end_clean();
170
+            }
171
+            is_callable($callback, true, $name);
172
+            $res[] = (object) [
173
+                'tab' => "Error in panel $name",
174
+                'panel' => nl2br(Helpers::escapeHtml($e)),
175
+            ];
176
+        }
177
+        return $res;
178
+    }
179
+
180
+
181
+    /**
182
+     * @return array[]
183
+     */
184
+    private function renderActions($ex)
185
+    {
186
+        $actions = [];
187
+        foreach ($this->actions as $callback) {
188
+            $action = call_user_func($callback, $ex);
189
+            if (!empty($action['link']) && !empty($action['label'])) {
190
+                $actions[] = $action;
191
+            }
192
+        }
193
+
194
+        if (property_exists($ex, 'tracyAction') && !empty($ex->tracyAction['link']) && !empty($ex->tracyAction['label'])) {
195
+            $actions[] = $ex->tracyAction;
196
+        }
197
+
198
+        if (preg_match('# ([\'"])(\w{3,}(?:\\\\\w{3,})+)\\1#i', $ex->getMessage(), $m)) {
199
+            $class = $m[2];
200
+            if (
201
+                !class_exists($class) && !interface_exists($class) && !trait_exists($class)
202
+                && ($file = Helpers::guessClassFile($class)) && !is_file($file)
203
+            ) {
204
+                $actions[] = [
205
+                    'link' => Helpers::editorUri($file, 1, 'create'),
206
+                    'label' => 'create class',
207
+                ];
208
+            }
209
+        }
210
+
211
+        if (preg_match('# ([\'"])((?:/|[a-z]:[/\\\\])\w[^\'"]+\.\w{2,5})\\1#i', $ex->getMessage(), $m)) {
212
+            $file = $m[2];
213
+            $actions[] = [
214
+                'link' => Helpers::editorUri($file, 1, $label = is_file($file) ? 'open' : 'create'),
215
+                'label' => $label . ' file',
216
+            ];
217
+        }
218
+
219
+        $query = ($ex instanceof \ErrorException ? '' : Helpers::getClass($ex) . ' ')
220
+            . preg_replace('#\'.*\'|".*"#Us', '', $ex->getMessage());
221
+        $actions[] = [
222
+            'link' => 'https://www.google.com/search?sourceid=tracy&q=' . urlencode($query),
223
+            'label' => 'search',
224
+            'external' => true,
225
+        ];
226
+
227
+        if (
228
+            $ex instanceof \ErrorException
229
+            && !empty($ex->skippable)
230
+            && preg_match('#^https?://#', $source = Helpers::getSource())
231
+        ) {
232
+            $actions[] = [
233
+                'link' => $source . (strpos($source, '?') ? '&' : '?') . '_tracy_skip_error',
234
+                'label' => 'skip error',
235
+            ];
236
+        }
237
+        return $actions;
238
+    }
239
+
240
+
241
+    /**
242
+     * Returns syntax highlighted source code.
243
+     * @param  string  $file
244
+     * @param  int  $line
245
+     * @param  int  $lines
246
+     * @return string|null
247
+     */
248
+    public static function highlightFile($file, $line, $lines = 15, array $vars = null)
249
+    {
250
+        $source = @file_get_contents($file); // @ file may not exist
251
+        if ($source) {
252
+            $source = static::highlightPhp($source, $line, $lines, $vars);
253
+            if ($editor = Helpers::editorUri($file, $line)) {
254
+                $source = substr_replace($source, ' data-tracy-href="' . Helpers::escapeHtml($editor) . '"', 4, 0);
255
+            }
256
+            return $source;
257
+        }
258
+    }
259
+
260
+
261
+    /**
262
+     * Returns syntax highlighted source code.
263
+     * @param  string  $source
264
+     * @param  int  $line
265
+     * @param  int  $lines
266
+     * @return string
267
+     */
268
+    public static function highlightPhp($source, $line, $lines = 15, array $vars = null)
269
+    {
270
+        if (function_exists('ini_set')) {
271
+            ini_set('highlight.comment', '#998; font-style: italic');
272
+            ini_set('highlight.default', '#000');
273
+            ini_set('highlight.html', '#06B');
274
+            ini_set('highlight.keyword', '#D24; font-weight: bold');
275
+            ini_set('highlight.string', '#080');
276
+        }
277
+
278
+        $source = str_replace(["\r\n", "\r"], "\n", $source);
279
+        $source = explode("\n", highlight_string($source, true));
280
+        $out = $source[0]; // <code><span color=highlight.html>
281
+        $source = str_replace('<br />', "\n", $source[1]);
282
+        $out .= static::highlightLine($source, $line, $lines);
283
+
284
+        if ($vars) {
285
+            $out = preg_replace_callback('#">\$(\w+)(&nbsp;)?</span>#', function ($m) use ($vars) {
286
+                return array_key_exists($m[1], $vars)
287
+                    ? '" title="'
288
+                        . str_replace('"', '&quot;', trim(strip_tags(Dumper::toHtml($vars[$m[1]], [Dumper::DEPTH => 1]))))
289
+                        . $m[0]
290
+                    : $m[0];
291
+            }, $out);
292
+        }
293
+
294
+        $out = str_replace('&nbsp;', ' ', $out);
295
+        return "<pre class='code'><div>$out</div></pre>";
296
+    }
297
+
298
+
299
+    /**
300
+     * Returns highlighted line in HTML code.
301
+     * @return string
302
+     */
303
+    public static function highlightLine($html, $line, $lines = 15)
304
+    {
305
+        $source = explode("\n", "\n" . str_replace("\r\n", "\n", $html));
306
+        $out = '';
307
+        $spans = 1;
308
+        $start = $i = max(1, min($line, count($source) - 1) - (int) floor($lines * 2 / 3));
309
+        while (--$i >= 1) { // find last highlighted block
310
+            if (preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) {
311
+                if ($m[1] !== '</span>') {
312
+                    $spans++;
313
+                    $out .= $m[1];
314
+                }
315
+                break;
316
+            }
317
+        }
318
+
319
+        $source = array_slice($source, $start, $lines, true);
320
+        end($source);
321
+        $numWidth = strlen((string) key($source));
322
+
323
+        foreach ($source as $n => $s) {
324
+            $spans += substr_count($s, '<span') - substr_count($s, '</span');
325
+            $s = str_replace(["\r", "\n"], ['', ''], $s);
326
+            preg_match_all('#<[^>]+>#', $s, $tags);
327
+            if ($n == $line) {
328
+                $out .= sprintf(
329
+                    "<span class='highlight'>%{$numWidth}s:    %s\n</span>%s",
330
+                    $n,
331
+                    strip_tags($s),
332
+                    implode('', $tags[0])
333
+                );
334
+            } else {
335
+                $out .= sprintf("<span class='line'>%{$numWidth}s:</span>    %s\n", $n, $s);
336
+            }
337
+        }
338
+        $out .= str_repeat('</span>', $spans) . '</code>';
339
+        return $out;
340
+    }
341
+
342
+
343
+    /**
344
+     * Should a file be collapsed in stack trace?
345
+     * @param  string  $file
346
+     * @return bool
347
+     */
348
+    public function isCollapsed($file)
349
+    {
350
+        $file = strtr($file, '\\', '/') . '/';
351
+        foreach ($this->collapsePaths as $path) {
352
+            $path = strtr($path, '\\', '/') . '/';
353
+            if (strncmp($file, $path, strlen($path)) === 0) {
354
+                return true;
355
+            }
356
+        }
357
+        return false;
358
+    }
359 359
 }
Please login to merge, or discard this patch.
core/vendor/tracy/tracy/src/Tracy/ILogger.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -13,13 +13,13 @@
 block discarded – undo
13 13
  */
14 14
 interface ILogger
15 15
 {
16
-	const
17
-		DEBUG = 'debug',
18
-		INFO = 'info',
19
-		WARNING = 'warning',
20
-		ERROR = 'error',
21
-		EXCEPTION = 'exception',
22
-		CRITICAL = 'critical';
16
+    const
17
+        DEBUG = 'debug',
18
+        INFO = 'info',
19
+        WARNING = 'warning',
20
+        ERROR = 'error',
21
+        EXCEPTION = 'exception',
22
+        CRITICAL = 'critical';
23 23
 
24
-	function log($value, $priority = self::INFO);
24
+    function log($value, $priority = self::INFO);
25 25
 }
Please login to merge, or discard this patch.