diff --git a/src/Tracy/Dumper.php b/src/Tracy/Dumper.php index 9c0643307..495a8c186 100644 --- a/src/Tracy/Dumper.php +++ b/src/Tracy/Dumper.php @@ -218,9 +218,8 @@ private static function dumpArray(&$var, array $options, int $level): string foreach ($var as $k => &$v) { if ($k !== $marker) { $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]) ? self::HIDDEN_VALUE : null; - $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . Helpers::escapeHtml(self::encodeString($k, $options[self::TRUNCATE])) . '"'; $out .= ' ' . str_repeat('| ', $level) . '' - . '' . $k . ' => ' + . '' . Helpers::escapeHtml(self::encodeKey($k, $options)) . ' => ' . ($hide ? self::dumpString($hide, $options) : self::dumpVar($v, $options, $level + 1)); } } @@ -275,9 +274,8 @@ private static function dumpObject(&$var, array $options, int $level): string $k = substr($k, strrpos($k, "\x00") + 1); } $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]) ? self::HIDDEN_VALUE : null; - $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . Helpers::escapeHtml(self::encodeString($k, $options[self::TRUNCATE])) . '"'; $out .= ' ' . str_repeat('| ', $level) . '' - . '' . $k . "$vis => " + . '' . Helpers::escapeHtml(self::encodeKey($k, $options)) . "$vis => " . ($hide ? self::dumpString($hide, $options) : self::dumpVar($v, $options, $level + 1)); } array_pop($list); @@ -335,8 +333,7 @@ private static function toJson(&$var, array $options, int $level = 0) foreach ($var as $k => &$v) { if ($k !== $marker) { $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]); - $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"'; - $res[] = [$k, $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1)]; + $res[] = [self::encodeKey($k, $options), $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1)]; } } unset($var[$marker]); @@ -374,8 +371,7 @@ private static function toJson(&$var, array $options, int $level = 0) $k = substr($k, strrpos($k, "\x00") + 1); } $hide = is_string($k) && isset($options[self::KEYS_TO_HIDE][strtolower($k)]); - $k = is_int($k) || preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"'; - $obj['items'][] = [$k, $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1), $vis]; + $obj['items'][] = [self::encodeKey($k, $options), $hide ? self::HIDDEN_VALUE : self::toJson($v, $options, $level + 1), $vis]; } } return ['object' => $obj['id']]; @@ -457,6 +453,18 @@ public static function encodeString(string $s, int $maxLength = null): string } + /** + * @param int|string $k + * @return int|string + */ + private static function encodeKey($key, array $options) + { + return is_int($key) || preg_match('#^[!\#$%&()*+,./0-9:;<=>?@A-Z[\]^_`a-z{|}~-]{1,50}\z#', $key) + ? $key + : '"' . self::encodeString($key, $options[self::TRUNCATE]) . '"'; + } + + /** * @param object $obj */ diff --git a/tests/Tracy/Dumper.keys.phpt b/tests/Tracy/Dumper.keys.phpt new file mode 100644 index 000000000..cbbd6b3c1 --- /dev/null +++ b/tests/Tracy/Dumper.keys.phpt @@ -0,0 +1,65 @@ + 0, + '"' => 0, + "'" => 0, + 'key' => 0, + ' key' => 0, + 'key ' => 0, + 0 => 0, + '01' => 0, +]; + +Assert::match('array (%i%) + "" => 0 + """ => 0 + "\'" => 0 + key => 0 + " key" => 0 + "key " => 0 + 0 => 0 + 01 => 0 +', Dumper::toText($keys)); + +Assert::match('stdClass #%a% + "" => 0 + """ => 0 + "\'" => 0 + key => 0 + " key" => 0 + "key " => 0 + 0 => 0 + 01 => 0 +', Dumper::toText((object) $keys)); + +Assert::match( + '
',
+	Dumper::toHtml((object) $keys, [Dumper::LIVE => true])
+);
+
+Assert::same([
+	'01' => [
+		'name' => 'stdClass',
+		'editor' => null,
+		'items' => [
+			['""', 0, 0],
+			['"""', 0, 0],
+			['"\'"', 0, 0],
+			['key', 0, 0],
+			['" key"', 0, 0],
+			['"key "', 0, 0],
+			[0, 0, 0],
+			['01', 0, 0],
+		],
+	],
+], Dumper::fetchLiveData());
diff --git a/tests/Tracy/Dumper.objectExporters.phpt b/tests/Tracy/Dumper.objectExporters.phpt
index a226f5943..5cee5d23c 100644
--- a/tests/Tracy/Dumper.objectExporters.phpt
+++ b/tests/Tracy/Dumper.objectExporters.phpt
@@ -39,9 +39,9 @@ $obj = unserialize('O:1:"Y":7:{s:1:"a";N;s:1:"b";i:2;s:4:"' . "\0" . '*' . "\0"
 Assert::match('__PHP_Incomplete_Class #%a%
    className => "Y"
    private => array (3)
-   |  "Y::$e" => null
-   |  "Y::$i" => "bar" (3)
-   |  "X::$i" => "foo" (3)
+   |  Y::$e => null
+   |  Y::$i => "bar" (3)
+   |  X::$i => "foo" (3)
    protected => array (2)
    |  c => null
    |  d => "d"