Skip to content

Commit d2fd8c7

Browse files
committed
Change how to stringify anonymous classes
The class name of an anonymous class can be long, so I decided to make it shorter. A simple "class" is enough to describe the class name since it is a reserved word, and that's how we define an anonymous class. If the anonymous class extends another class, it makes sense to keep the extended class name while ensuring the user understands it is anonymous. In those cases, I kept the same behavior as PHP, with "@anonymous" next to the extended class name. Signed-off-by: Henrique Moody <[email protected]>
1 parent a27ea6a commit d2fd8c7

14 files changed

+135
-41
lines changed

src/Helpers/ObjectHelper.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Respect/Stringifier.
5+
* Copyright (c) Henrique Moody <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace Respect\Stringifier\Helpers;
12+
13+
use function array_filter;
14+
use function count;
15+
use function implode;
16+
use function sprintf;
17+
use function strstr;
18+
19+
trait ObjectHelper
20+
{
21+
private function format(object $object, ?string ...$pieces): string
22+
{
23+
$filteredPieces = array_filter($pieces);
24+
if (count($filteredPieces) === 0) {
25+
return $this->getName($object) . ' {}';
26+
}
27+
28+
return sprintf('%s { %s }', $this->getName($object), implode(' ', $filteredPieces));
29+
}
30+
31+
private function getName(object $object): string
32+
{
33+
$name = strstr($object::class, "\000", true);
34+
if ($name === 'class@anonymous') {
35+
return 'class';
36+
}
37+
38+
if ($name !== false) {
39+
return $name;
40+
}
41+
42+
return $object::class;
43+
}
44+
}

src/Stringifiers/DateTimeStringifier.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
namespace Respect\Stringifier\Stringifiers;
1212

1313
use DateTimeInterface;
14+
use Respect\Stringifier\Helpers\ObjectHelper;
1415
use Respect\Stringifier\Quoter;
1516
use Respect\Stringifier\Stringifier;
1617

17-
use function sprintf;
18-
1918
final class DateTimeStringifier implements Stringifier
2019
{
20+
use ObjectHelper;
21+
2122
public function __construct(
2223
private readonly Quoter $quoter,
2324
private readonly string $format
@@ -30,6 +31,6 @@ public function stringify(mixed $raw, int $depth): ?string
3031
return null;
3132
}
3233

33-
return $this->quoter->quote(sprintf('%s { %s }', $raw::class, $raw->format($this->format)), $depth);
34+
return $this->quoter->quote($this->format($raw, $raw->format($this->format)), $depth);
3435
}
3536
}

src/Stringifiers/IteratorObjectStringifier.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
namespace Respect\Stringifier\Stringifiers;
1212

1313
use Iterator;
14+
use Respect\Stringifier\Helpers\ObjectHelper;
1415
use Respect\Stringifier\Quoter;
1516
use Respect\Stringifier\Stringifier;
1617

17-
use function sprintf;
18-
1918
final class IteratorObjectStringifier implements Stringifier
2019
{
20+
use ObjectHelper;
21+
2122
public function __construct(
2223
private readonly Stringifier $stringifier,
2324
private readonly Quoter $quoter
@@ -31,11 +32,7 @@ public function stringify(mixed $raw, int $depth): ?string
3132
}
3233

3334
return $this->quoter->quote(
34-
sprintf(
35-
'%s { current() => %s }',
36-
$raw::class,
37-
$this->stringifier->stringify($raw->current(), $depth + 1)
38-
),
35+
$this->format($raw, 'current() =>', $this->stringifier->stringify($raw->current(), $depth + 1)),
3936
$depth
4037
);
4138
}

src/Stringifiers/JsonSerializableObjectStringifier.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
namespace Respect\Stringifier\Stringifiers;
1212

1313
use JsonSerializable;
14+
use Respect\Stringifier\Helpers\ObjectHelper;
1415
use Respect\Stringifier\Quoter;
1516
use Respect\Stringifier\Stringifier;
1617

17-
use function sprintf;
18-
1918
final class JsonSerializableObjectStringifier implements Stringifier
2019
{
20+
use ObjectHelper;
21+
2122
public function __construct(
2223
private readonly Stringifier $stringifier,
2324
private readonly Quoter $quoter
@@ -31,11 +32,7 @@ public function stringify(mixed $raw, int $depth): ?string
3132
}
3233

3334
return $this->quoter->quote(
34-
sprintf(
35-
'%s { jsonSerialize() => %s }',
36-
$raw::class,
37-
$this->stringifier->stringify($raw->jsonSerialize(), $depth + 1)
38-
),
35+
$this->format($raw, 'jsonSerialize() =>', $this->stringifier->stringify($raw->jsonSerialize(), $depth + 1)),
3936
$depth
4037
);
4138
}

src/Stringifiers/ObjectStringifier.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212

1313
use ReflectionObject;
1414
use ReflectionProperty;
15+
use Respect\Stringifier\Helpers\ObjectHelper;
1516
use Respect\Stringifier\Quoter;
1617
use Respect\Stringifier\Stringifier;
1718

1819
use function count;
19-
use function implode;
2020
use function is_object;
2121
use function sprintf;
2222
use function trim;
2323

2424
final class ObjectStringifier implements Stringifier
2525
{
26+
use ObjectHelper;
27+
2628
private const LIMIT_EXCEEDED_PLACEHOLDER = '...';
2729

2830
public function __construct(
@@ -40,15 +42,13 @@ public function stringify(mixed $raw, int $depth): ?string
4042
}
4143

4244
if ($depth >= $this->maximumDepth) {
43-
return $this->quoter->quote(sprintf('%s { %s }', $raw::class, self::LIMIT_EXCEEDED_PLACEHOLDER), $depth);
44-
}
45-
46-
$properties = $this->getProperties(new ReflectionObject($raw), $raw, $depth + 1);
47-
if (count($properties) === 0) {
48-
return $this->quoter->quote(sprintf('%s {}', $raw::class), $depth);
45+
return $this->quoter->quote($this->format($raw, self::LIMIT_EXCEEDED_PLACEHOLDER), $depth);
4946
}
5047

51-
return $this->quoter->quote(sprintf('%s { %s }', $raw::class, implode(' ', $properties)), $depth);
48+
return $this->quoter->quote(
49+
$this->format($raw, ...$this->getProperties(new ReflectionObject($raw), $raw, $depth + 1)),
50+
$depth
51+
);
5252
}
5353

5454
/**

src/Stringifiers/StringableObjectStringifier.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010

1111
namespace Respect\Stringifier\Stringifiers;
1212

13+
use Respect\Stringifier\Helpers\ObjectHelper;
1314
use Respect\Stringifier\Quoter;
1415
use Respect\Stringifier\Stringifier;
1516
use Stringable;
1617

17-
use function sprintf;
18-
1918
final class StringableObjectStringifier implements Stringifier
2019
{
20+
use ObjectHelper;
21+
2122
public function __construct(
2223
private readonly Stringifier $stringifier,
2324
private readonly Quoter $quoter
@@ -31,11 +32,7 @@ public function stringify(mixed $raw, int $depth): ?string
3132
}
3233

3334
return $this->quoter->quote(
34-
sprintf(
35-
'%s { __toString() => %s }',
36-
$raw::class,
37-
$this->stringifier->stringify($raw->__toString(), $depth + 1)
38-
),
35+
$this->format($raw, '__toString() =>', $this->stringifier->stringify($raw->__toString(), $depth + 1)),
3936
$depth
4037
);
4138
}

src/Stringifiers/ThrowableObjectStringifier.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010

1111
namespace Respect\Stringifier\Stringifiers;
1212

13+
use Respect\Stringifier\Helpers\ObjectHelper;
1314
use Respect\Stringifier\Quoter;
1415
use Respect\Stringifier\Stringifier;
1516
use Throwable;
1617

1718
use function getcwd;
18-
use function sprintf;
1919
use function str_replace;
2020

2121
final class ThrowableObjectStringifier implements Stringifier
2222
{
23+
use ObjectHelper;
24+
2325
public function __construct(
2426
private readonly Stringifier $stringifier,
2527
private readonly Quoter $quoter
@@ -33,18 +35,15 @@ public function stringify(mixed $raw, int $depth): ?string
3335
}
3436

3537
if ($raw->getMessage() === '') {
36-
return $this->quoter->quote(
37-
sprintf('%s { in %s }', $raw::class, $this->getSource($raw)),
38-
$depth
39-
);
38+
return $this->quoter->quote($this->format($raw, 'in', $this->getSource($raw)), $depth);
4039
}
4140

4241
return $this->quoter->quote(
43-
sprintf(
44-
'%s { %s in %s }',
45-
$raw::class,
42+
$this->format(
43+
$raw,
4644
$this->stringifier->stringify($raw->getMessage(), $depth + 1),
47-
$this->getSource($raw),
45+
'in',
46+
$this->getSource($raw)
4847
),
4948
$depth
5049
);

tests/integration/stringify-object.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ outputMultiple(
99
new stdClass(),
1010
new WithProperties(),
1111
new WithUninitializedProperties(),
12+
new class {
13+
},
1214
);
1315
?>
1416
--EXPECT--
1517
`stdClass {}`
1618
`WithProperties { +$publicProperty=true #$protectedProperty=42 -$privateProperty="something" }`
1719
`WithUninitializedProperties { +$uninitializedProperty=*uninitialized* }`
20+
`class {}`

tests/unit/Stringifiers/DateTimeStringifierTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
use PHPUnit\Framework\Attributes\DataProvider;
1818
use PHPUnit\Framework\Attributes\Test;
1919
use PHPUnit\Framework\TestCase;
20+
use Respect\Stringifier\Helpers\ObjectHelper;
2021
use Respect\Stringifier\Stringifiers\DateTimeStringifier;
2122
use Respect\Stringifier\Test\Double\FakeQuoter;
2223

24+
#[CoversClass(ObjectHelper::class)]
2325
#[CoversClass(DateTimeStringifier::class)]
2426
final class DateTimeStringifierTest extends TestCase
2527
{

tests/unit/Stringifiers/IteratorObjectStringifierTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
use PHPUnit\Framework\Attributes\CoversClass;
1515
use PHPUnit\Framework\Attributes\Test;
1616
use PHPUnit\Framework\TestCase;
17+
use Respect\Stringifier\Helpers\ObjectHelper;
1718
use Respect\Stringifier\Stringifiers\IteratorObjectStringifier;
1819
use Respect\Stringifier\Test\Double\FakeQuoter;
1920
use Respect\Stringifier\Test\Double\FakeStringifier;
2021

2122
use function sprintf;
2223

24+
#[CoversClass(ObjectHelper::class)]
2325
#[CoversClass(IteratorObjectStringifier::class)]
2426
final class IteratorObjectStringifierTest extends TestCase
2527
{

0 commit comments

Comments
 (0)