Skip to content

Commit

Permalink
Render anonymous classes correctly on php 8.
Browse files Browse the repository at this point in the history
  • Loading branch information
derrabus committed May 22, 2020
1 parent 6d7c696 commit 2a057ad
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 18 deletions.
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -31,7 +31,8 @@
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php72": "~1.5",
"symfony/polyfill-php73": "^1.11"
"symfony/polyfill-php73": "^1.11",
"symfony/polyfill-php80": "^1.17"
},
"replace": {
"symfony/asset": "self.version",
Expand Down
13 changes: 8 additions & 5 deletions src/Symfony/Component/Console/Application.php
Expand Up @@ -863,17 +863,20 @@ private function doActuallyRenderThrowable(\Throwable $e, OutputInterface $outpu
do {
$message = trim($e->getMessage());
if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
$class = \get_class($e);
$class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
$class = \get_debug_type($e);
$title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
$len = Helper::strlen($title);
} else {
$len = 0;
}

if (false !== strpos($message, "class@anonymous\0")) {
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
if (str_contains($message, "@anonymous\0")) {
$message = preg_replace_callback('/([\\\\\w]+)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
if ('class' === $m[1]) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
}

return $m[1].'@anonymous';
}, $message);
}

Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Console/composer.json
Expand Up @@ -19,6 +19,7 @@
"php": ">=7.1.3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8",
"symfony/polyfill-php80": "^1.17",
"symfony/service-contracts": "^1.1|^2"
},
"require-dev": {
Expand Down
Expand Up @@ -26,7 +26,7 @@ class FatalThrowableError extends FatalErrorException

public function __construct(\Throwable $e)
{
$this->originalClassName = \get_class($e);
$this->originalClassName = \get_debug_type($e);

if ($e instanceof \ParseError) {
$severity = E_PARSE;
Expand Down
18 changes: 13 additions & 5 deletions src/Symfony/Component/Debug/Exception/FlattenException.php
Expand Up @@ -67,7 +67,7 @@ public static function createFromThrowable(\Throwable $exception, int $statusCod
$e->setStatusCode($statusCode);
$e->setHeaders($headers);
$e->setTraceFromThrowable($exception);
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception));
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_debug_type($exception));
$e->setFile($exception->getFile());
$e->setLine($exception->getLine());

Expand Down Expand Up @@ -134,7 +134,11 @@ public function getClass()
*/
public function setClass($class)
{
$this->class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
if (preg_match('/^([\\\\\w]+)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', $class, $matches)) {
$this->class = ('class' === $matches[1] ? get_parent_class($matches[0]) : $matches[1]).'@anonymous';
} else {
$this->class = $class;
}

return $this;
}
Expand Down Expand Up @@ -179,9 +183,13 @@ public function getMessage()
*/
public function setMessage($message)
{
if (false !== strpos($message, "class@anonymous\0")) {
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
if (str_contains($message, "@anonymous\0")) {
$message = preg_replace_callback('/([\\\\\w]+)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
if ('class' === $m[1]) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
}

return $m[1].'@anonymous';
}, $message);
}

Expand Down
Expand Up @@ -355,6 +355,11 @@ public function testAnonymousClass()

$this->assertSame('RuntimeException@anonymous', $flattened->getClass());

$flattened->setClass(get_class(new class('Oops') extends NotFoundHttpException {
}));

$this->assertSame('Symfony\Component\HttpKernel\Exception\NotFoundHttpException@anonymous', $flattened->getClass());

$flattened = FlattenException::create(new \Exception(sprintf('Class "%s" blah.', \get_class(new class() extends \RuntimeException {
}))));

Expand Down
3 changes: 2 additions & 1 deletion src/Symfony/Component/Debug/composer.json
Expand Up @@ -17,7 +17,8 @@
],
"require": {
"php": ">=7.1.3",
"psr/log": "~1.0"
"psr/log": "~1.0",
"symfony/polyfill-php80": "~1.17"
},
"conflict": {
"symfony/http-kernel": "<3.4"
Expand Down
18 changes: 13 additions & 5 deletions src/Symfony/Component/ErrorHandler/Exception/FlattenException.php
Expand Up @@ -71,7 +71,7 @@ public static function createFromThrowable(\Throwable $exception, int $statusCod
$e->setStatusCode($statusCode);
$e->setHeaders($headers);
$e->setTraceFromThrowable($exception);
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception));
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_debug_type($exception));
$e->setFile($exception->getFile());
$e->setLine($exception->getLine());

Expand Down Expand Up @@ -138,7 +138,11 @@ public function getClass(): string
*/
public function setClass($class): self
{
$this->class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
if (preg_match('/^([\\\\\w]+)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', $class, $matches)) {
$this->class = ('class' === $matches[1] ? get_parent_class($matches[0]) : $matches[1]).'@anonymous';
} else {
$this->class = $class;
}

return $this;
}
Expand Down Expand Up @@ -195,9 +199,13 @@ public function getMessage(): string
*/
public function setMessage($message): self
{
if (false !== strpos($message, "class@anonymous\0")) {
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
if (str_contains($message, "@anonymous\0")) {
$message = preg_replace_callback('/([\\\\\w]+)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
if ('class' === $m[1]) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
}

return $m[1].'@anonymous';
}, $message);
}

Expand Down
Expand Up @@ -373,6 +373,11 @@ public function testAnonymousClass()

$this->assertSame('RuntimeException@anonymous', $flattened->getClass());

$flattened->setClass(get_class(new class('Oops') extends NotFoundHttpException {
}));

$this->assertSame('Symfony\Component\HttpKernel\Exception\NotFoundHttpException@anonymous', $flattened->getClass());

$flattened = FlattenException::createFromThrowable(new \Exception(sprintf('Class "%s" blah.', \get_class(new class() extends \RuntimeException {
}))));

Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/ErrorHandler/composer.json
Expand Up @@ -19,6 +19,7 @@
"php": ">=7.1.3",
"psr/log": "~1.0",
"symfony/debug": "^4.4.5",
"symfony/polyfill-php80": "^1.17",
"symfony/var-dumper": "^4.4|^5.0"
},
"require-dev": {
Expand Down

0 comments on commit 2a057ad

Please sign in to comment.