diff --git a/composer.json b/composer.json index 78a65ec..e9959a9 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,10 @@ ], "require": { "php": "^7.2", - "symfony/polyfill-ctype": "^1.8.0" + "symfony/polyfill-mbstring": "^1.8.0" }, "require-dev": { - "narrowspark/php-cs-fixer-config": "^2.1.0", + "narrowspark/php-cs-fixer-config": "^3.0.1", "phpstan/phpstan": "^0.9.0", "phpstan/phpstan-phpunit": "^0.9.0", "phpunit/phpunit": "^7.0.0", diff --git a/src/Traits/PrettyArrayPrintTrait.php b/src/Traits/PrettyArrayPrintTrait.php index 01eddd3..ecf8978 100644 --- a/src/Traits/PrettyArrayPrintTrait.php +++ b/src/Traits/PrettyArrayPrintTrait.php @@ -19,8 +19,8 @@ protected static function getPrettyPrintArray(array $data, int $indentLevel = 1) foreach ($data as $key => $value) { if (! \is_int($key)) { - if (\is_string($key) && (\class_exists($key) || \interface_exists($key)) && \ctype_upper($key[0])) { - $key = \sprintf('\\%s::class', \ltrim($key, '\\')); + if (self::isClass($key)) { + $key = self::dumpLiteralClass($key); } else { $key = \sprintf("'%s'", $key); } @@ -53,8 +53,8 @@ protected static function createValue($value, int $indentLevel): string return self::getPrettyPrintArray($value, $indentLevel + 1); } - if (\is_string($value) && (\class_exists($value) || \interface_exists($value)) && \ctype_upper($value[0])) { - return \sprintf('\\%s::class', \ltrim($value, '\\')); + if (self::isClass($value)) { + return self::dumpLiteralClass($value); } if (\is_numeric($value)) { @@ -67,4 +67,38 @@ protected static function createValue($value, int $indentLevel): string return \var_export($value, true); } + + /** + * Dumps a string to a literal (aka PHP Code) class value. + * + * @param string $class + * + * @return string + */ + private static function dumpLiteralClass(string $class): string + { + $class = \str_replace('\\\\', '\\', $class); + $class = \sprintf('%s::class', $class); + + return \mb_strpos($class, '\\') === 0 ? $class : '\\' . $class; + } + + /** + * Check if entry is a class. + * + * @param mixed $key + * + * @return bool + */ + private static function isClass($key): bool + { + if (! \is_string($key)) { + return false; + } + + $key = \ltrim($key, '\\'); + $firstChar = \mb_substr($key, 0, 1); + + return (\class_exists($key) || \interface_exists($key)) && \mb_strtolower($firstChar) !== $firstChar; + } } diff --git a/tests/PrettyArrayTest.php b/tests/PrettyArrayTest.php index 39f622e..dbae3e3 100644 --- a/tests/PrettyArrayTest.php +++ b/tests/PrettyArrayTest.php @@ -7,19 +7,23 @@ use PHPUnit\Framework\TestCase; use Throwable; -class PrettyArrayTest extends TestCase +/** + * @internal + */ +final class PrettyArrayTest extends TestCase { public function arrayOutProvider(): array { return [ [[], '[' . \PHP_EOL . \PHP_EOL . ']'], - [[1], '[' . PHP_EOL . ' 0 => 1,' . PHP_EOL . ']'], - [[1, 2, 3], '[' . PHP_EOL . ' 0 => 1,' . PHP_EOL . ' 1 => 2,' . PHP_EOL . ' 2 => 3,' . PHP_EOL . ']'], - [[1, '2', 3], '[' . PHP_EOL . ' 0 => 1,' . PHP_EOL . ' 1 => \'2\',' . PHP_EOL . ' 2 => 3,' . PHP_EOL . ']'], - [['foo' => 1, [2, 3]], '[' . PHP_EOL . ' \'foo\' => 1,' . PHP_EOL . ' 0 => [' . PHP_EOL . ' 0 => 2,' . PHP_EOL . ' 1 => 3,' . PHP_EOL . ' ],' . PHP_EOL . ']'], - [[1 => ['foo'], 'bar' => 2], '[' . PHP_EOL . ' 1 => [' . PHP_EOL . ' 0 => \'foo\',' . PHP_EOL . ' ],' . PHP_EOL . ' \'bar\' => 2,' . PHP_EOL . ']'], - [[1 => Exception::class, Throwable::class => 'error', 'foo' => 'bar', 'fooa' => 1.2], '[' . PHP_EOL . ' 1 => \\Exception::class,' . PHP_EOL . ' \\Throwable::class => \'error\',' . PHP_EOL . ' \'foo\' => \'bar\',' . PHP_EOL . ' \'fooa\' => 1.2,' . PHP_EOL . ']'], - [[1 => 'foo', '188.29614911019327165' => 'bar', 'foo' => '889614911019327165', 'fooa' => 18896141256], '[' . PHP_EOL . ' 1 => \'foo\',' . PHP_EOL . ' \'188.29614911019327165\' => \'bar\',' . PHP_EOL . ' \'foo\' => \'889614911019327165\',' . PHP_EOL . ' \'fooa\' => 18896141256,' . PHP_EOL . ']'], + [[1], '[' . \PHP_EOL . ' 0 => 1,' . \PHP_EOL . ']'], + [[1, 2, 3], '[' . \PHP_EOL . ' 0 => 1,' . \PHP_EOL . ' 1 => 2,' . \PHP_EOL . ' 2 => 3,' . \PHP_EOL . ']'], + [[1, '2', 3], '[' . \PHP_EOL . ' 0 => 1,' . \PHP_EOL . ' 1 => \'2\',' . \PHP_EOL . ' 2 => 3,' . \PHP_EOL . ']'], + [['foo' => 1, [2, 3]], '[' . \PHP_EOL . ' \'foo\' => 1,' . \PHP_EOL . ' 0 => [' . \PHP_EOL . ' 0 => 2,' . \PHP_EOL . ' 1 => 3,' . \PHP_EOL . ' ],' . \PHP_EOL . ']'], + [[1 => ['foo'], 'bar' => 2], '[' . \PHP_EOL . ' 1 => [' . \PHP_EOL . ' 0 => \'foo\',' . \PHP_EOL . ' ],' . \PHP_EOL . ' \'bar\' => 2,' . \PHP_EOL . ']'], + [['\\Exception', '\\\\' . Exception::class], '[' . \PHP_EOL . ' 0 => \\Exception::class,' . \PHP_EOL . ' 1 => \\Exception::class,' . \PHP_EOL . ']'], + [[1 => Exception::class, Throwable::class => 'error', 'foo' => 'bar', 'fooa' => 1.2], '[' . \PHP_EOL . ' 1 => \\Exception::class,' . \PHP_EOL . ' \\Throwable::class => \'error\',' . \PHP_EOL . ' \'foo\' => \'bar\',' . \PHP_EOL . ' \'fooa\' => 1.2,' . \PHP_EOL . ']'], + [[1 => 'foo', '188.29614911019327165' => 'bar', 'foo' => '889614911019327165', 'fooa' => 18896141256], '[' . \PHP_EOL . ' 1 => \'foo\',' . \PHP_EOL . ' \'188.29614911019327165\' => \'bar\',' . \PHP_EOL . ' \'foo\' => \'889614911019327165\',' . \PHP_EOL . ' \'fooa\' => 18896141256,' . \PHP_EOL . ']'], ]; } @@ -31,6 +35,6 @@ public function arrayOutProvider(): array */ public function testConvertsValueToValidPhp($array, $expected): void { - self::assertEquals($expected, PrettyArray::print($array)); + $this->assertEquals($expected, PrettyArray::print($array)); } }