Skip to content

Commit de876a9

Browse files
committed
Create ThrowableStringifier
1 parent 070e261 commit de876a9

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Respect/Stringifier.
5+
*
6+
* (c) Henrique Moody <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the "LICENSE.md"
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Respect\Stringifier\Stringifiers;
15+
16+
use function get_class;
17+
use function getcwd;
18+
use function sprintf;
19+
use function str_replace;
20+
use Respect\Stringifier\Quoter;
21+
use Respect\Stringifier\Stringifier;
22+
use Throwable;
23+
24+
/**
25+
* Converts an instance of Throwable into a string.
26+
*
27+
* @author Henrique Moody <[email protected]>
28+
*/
29+
final class ThrowableStringifier implements Stringifier
30+
{
31+
/**
32+
* @var Stringifier
33+
*/
34+
private $stringifier;
35+
36+
/**
37+
* @var Quoter
38+
*/
39+
private $quoter;
40+
41+
/**
42+
* Initializes the stringifier.
43+
*
44+
* @param Stringifier $stringifier
45+
* @param Quoter $quoter
46+
*/
47+
public function __construct(Stringifier $stringifier, Quoter $quoter)
48+
{
49+
$this->stringifier = $stringifier;
50+
$this->quoter = $quoter;
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function stringify($raw, int $depth): ?string
57+
{
58+
if (!$raw instanceof Throwable) {
59+
return null;
60+
}
61+
62+
return $this->quoter->quote(
63+
sprintf(
64+
'[throwable] (%s: %s)',
65+
get_class($raw),
66+
$this->stringifier->stringify($this->getData($raw), $depth + 1)
67+
),
68+
$depth
69+
);
70+
}
71+
72+
private function getData(Throwable $throwable): array
73+
{
74+
return [
75+
'message' => $throwable->getMessage(),
76+
'code' => $throwable->getCode(),
77+
'file' => sprintf(
78+
'%s:%d',
79+
str_replace(getcwd().'/', '', $throwable->getFile()),
80+
$throwable->getLine()
81+
),
82+
];
83+
}
84+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Respect/Stringifier.
5+
*
6+
* (c) Henrique Moody <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the "LICENSE.md"
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Respect\Stringifier\Test\Stringifiers;
15+
16+
use Error;
17+
use ErrorException;
18+
use Exception;
19+
use function get_class;
20+
use function sprintf;
21+
use Respect\Stringifier\Quoter;
22+
use Respect\Stringifier\Stringifier;
23+
use Respect\Stringifier\Stringifiers\ThrowableStringifier;
24+
use PHPUnit\Framework\TestCase;
25+
use stdClass;
26+
use Throwable;
27+
use TypeError;
28+
29+
/**
30+
* @covers \Respect\Stringifier\Stringifiers\ThrowableStringifier
31+
*
32+
* @author Henrique Moody <[email protected]>
33+
*/
34+
final class ThrowableStringifierTest extends TestCase
35+
{
36+
/**
37+
* @test
38+
*
39+
* @dataProvider validValuesProvider
40+
*
41+
* @param Throwable $raw
42+
* @param int $line
43+
*/
44+
public function shouldConvertThrowableToString(Throwable $raw, int $line): void
45+
{
46+
$depth = 1;
47+
48+
$stringifiedData = '-stringifed-';
49+
50+
$expectedValue = sprintf(
51+
'[throwable] (%s: %s)',
52+
get_class($raw),
53+
$stringifiedData
54+
);
55+
56+
$expectedData = [
57+
'message' => $raw->getMessage(),
58+
'code' => $raw->getCode(),
59+
'file' => 'tests/unit/Stringifiers/ThrowableStringifierTest.php:'.$line,
60+
];
61+
62+
$stringifierMock = $this->createMock(Stringifier::class);
63+
$stringifierMock
64+
->expects($this->once())
65+
->method('stringify')
66+
->with($expectedData, $depth + 1)
67+
->willReturn($stringifiedData);
68+
69+
$quoterMock = $this->createMock(Quoter::class);
70+
$quoterMock
71+
->expects($this->once())
72+
->method('quote')
73+
->with($expectedValue, $depth)
74+
->willReturn($expectedValue);
75+
76+
$throwableStringifier = new ThrowableStringifier($stringifierMock, $quoterMock);
77+
78+
self::assertSame($expectedValue, $throwableStringifier->stringify($raw, $depth));
79+
}
80+
81+
public function validValuesProvider(): array
82+
{
83+
$line = 85;
84+
85+
return [
86+
[new Exception('Message for Exception', 0), ++$line],
87+
[new ErrorException('Message for ErrorException', 102), ++$line],
88+
[new Error('Message for Error', 78), ++$line],
89+
[new TypeError('Message for TypeError', 1009), ++$line],
90+
];
91+
}
92+
93+
/**
94+
* @test
95+
*/
96+
public function shouldReturnNullWhenNotInstanceOfThrowable(): void
97+
{
98+
$stringifierMock = $this->createMock(Stringifier::class);
99+
$stringifierMock
100+
->expects($this->never())
101+
->method('stringify');
102+
103+
$quoterMock = $this->createMock(Quoter::class);
104+
$quoterMock
105+
->expects($this->never())
106+
->method('quote');
107+
108+
$throwableStringifier = new ThrowableStringifier($stringifierMock, $quoterMock);
109+
110+
self::assertNull($throwableStringifier->stringify(new stdClass(), 0));
111+
}
112+
}

0 commit comments

Comments
 (0)