Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ce625dc

Browse filesBrowse files
committed
Parse and render anonymous classes correctly on php 8.
1 parent a14d8f9 commit ce625dc
Copy full SHA for ce625dc
Expand file treeCollapse file tree

23 files changed

+156
-51
lines changed

‎src/Symfony/Component/Console/Application.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Application.php
+8-5Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -863,17 +863,20 @@ private function doActuallyRenderThrowable(\Throwable $e, OutputInterface $outpu
863863
do {
864864
$message = trim($e->getMessage());
865865
if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
866-
$class = \get_class($e);
867-
$class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
866+
$class = get_debug_type($e);
868867
$title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
869868
$len = Helper::strlen($title);
870869
} else {
871870
$len = 0;
872871
}
873872

874-
if (false !== strpos($message, "class@anonymous\0")) {
875-
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
876-
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
873+
if (str_contains($message, "@anonymous\0")) {
874+
$message = preg_replace_callback('/([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', static function ($m) {
875+
if ('class' === $m[1]) {
876+
return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: 'class').'@anonymous' : $m[0];
877+
}
878+
879+
return $m[1].'@anonymous';
877880
}, $message);
878881
}
879882

‎src/Symfony/Component/Console/Tests/ApplicationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/ApplicationTest.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ public function testRenderAnonymousException()
912912
$tester = new ApplicationTester($application);
913913

914914
$tester->run(['command' => 'foo'], ['decorated' => false]);
915-
$this->assertStringContainsString('Dummy type "@anonymous" is invalid.', $tester->getDisplay(true));
915+
$this->assertStringContainsString('Dummy type "class@anonymous" is invalid.', $tester->getDisplay(true));
916916
}
917917

918918
public function testRenderExceptionStackTraceContainsRootException()
@@ -935,7 +935,7 @@ public function testRenderExceptionStackTraceContainsRootException()
935935
$tester = new ApplicationTester($application);
936936

937937
$tester->run(['command' => 'foo'], ['decorated' => false]);
938-
$this->assertStringContainsString('Dummy type "@anonymous" is invalid.', $tester->getDisplay(true));
938+
$this->assertStringContainsString('Dummy type "class@anonymous" is invalid.', $tester->getDisplay(true));
939939
}
940940

941941
public function testRun()

‎src/Symfony/Component/Console/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/composer.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"php": ">=7.1.3",
2020
"symfony/polyfill-mbstring": "~1.0",
2121
"symfony/polyfill-php73": "^1.8",
22+
"symfony/polyfill-php80": "^1.17",
2223
"symfony/service-contracts": "^1.1|^2"
2324
},
2425
"require-dev": {

‎src/Symfony/Component/Debug/ErrorHandler.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/ErrorHandler.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ public function handleError($type, $message, $file, $line)
415415
$context = $e;
416416
}
417417

418-
if (false !== strpos($message, "class@anonymous\0")) {
418+
if (false !== strpos($message, "@anonymous\0")) {
419419
$logMessage = $this->levels[$type].': '.(new FlattenException())->setMessage($message)->getMessage();
420420
} else {
421421
$logMessage = $this->levels[$type].': '.$message;
@@ -540,7 +540,7 @@ public function handleException($exception, array $error = null)
540540
$handlerException = null;
541541

542542
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
543-
if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) {
543+
if (false !== strpos($message = $exception->getMessage(), "@anonymous\0")) {
544544
$message = (new FlattenException())->setMessage($message)->getMessage();
545545
}
546546
if ($exception instanceof FatalErrorException) {

‎src/Symfony/Component/Debug/Exception/FatalThrowableError.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/Exception/FatalThrowableError.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class FatalThrowableError extends FatalErrorException
2626

2727
public function __construct(\Throwable $e)
2828
{
29-
$this->originalClassName = \get_class($e);
29+
$this->originalClassName = get_debug_type($e);
3030

3131
if ($e instanceof \ParseError) {
3232
$severity = E_PARSE;

‎src/Symfony/Component/Debug/Exception/FlattenException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/Exception/FlattenException.php
+13-5Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public static function createFromThrowable(\Throwable $exception, int $statusCod
6767
$e->setStatusCode($statusCode);
6868
$e->setHeaders($headers);
6969
$e->setTraceFromThrowable($exception);
70-
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception));
70+
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : get_debug_type($exception));
7171
$e->setFile($exception->getFile());
7272
$e->setLine($exception->getLine());
7373

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

139143
return $this;
140144
}
@@ -179,9 +183,13 @@ public function getMessage()
179183
*/
180184
public function setMessage($message)
181185
{
182-
if (false !== strpos($message, "class@anonymous\0")) {
183-
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
184-
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
186+
if (str_contains($message, "@anonymous\0")) {
187+
$message = preg_replace_callback('/([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', static function ($m) {
188+
if ('class' === $m[1]) {
189+
return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: 'class').'@anonymous' : $m[0];
190+
}
191+
192+
return $m[1].'@anonymous';
185193
}, $message);
186194
}
187195

‎src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,24 @@ public function testHandleUserError()
325325
}
326326
}
327327

328+
public function testHandleErrorWithAnonymousClass(): void
329+
{
330+
$handler = ErrorHandler::register();
331+
$handler->throwAt(E_USER_WARNING, true);
332+
try {
333+
$handler->handleError(E_USER_WARNING, 'foo '.\get_class(new class() extends \stdClass {
334+
}).' bar', 'foo.php', 12);
335+
$this->fail('Exception expected.');
336+
} catch (\ErrorException $e) {
337+
$this->assertSame('User Warning: foo stdClass@anonymous bar', $e->getMessage());
338+
$this->assertSame(E_USER_WARNING, $e->getSeverity());
339+
$this->assertSame('foo.php', $e->getFile());
340+
$this->assertSame(12, $e->getLine());
341+
} finally {
342+
restore_error_handler();
343+
}
344+
}
345+
328346
public function testHandleDeprecation()
329347
{
330348
$logArgCheck = function ($level, $message, $context) {

‎src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ public function testAnonymousClass()
355355

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

358+
$flattened->setClass(\get_class(new class('Oops') extends NotFoundHttpException {
359+
}));
360+
361+
$this->assertSame('Symfony\Component\HttpKernel\Exception\NotFoundHttpException@anonymous', $flattened->getClass());
362+
358363
$flattened = FlattenException::create(new \Exception(sprintf('Class "%s" blah.', \get_class(new class() extends \RuntimeException {
359364
}))));
360365

‎src/Symfony/Component/Debug/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/composer.json
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"require": {
1919
"php": ">=7.1.3",
20-
"psr/log": "~1.0"
20+
"psr/log": "~1.0",
21+
"symfony/polyfill-php80": "~1.17"
2122
},
2223
"conflict": {
2324
"symfony/http-kernel": "<3.4"

‎src/Symfony/Component/ErrorHandler/DebugClassLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/ErrorHandler/DebugClassLoader.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array
407407
}
408408
$deprecations = [];
409409

410-
$className = isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00") ? get_parent_class($class).'@anonymous' : $class;
410+
$className = $refl->isAnonymous() ? (($parentRefl = $refl->getParentClass()) ? $parentRefl->name : 'class').'@anonymous' : $class;
411411

412412
// Don't trigger deprecations for classes in the same vendor
413413
if ($class !== $className) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.