Skip to content

Commit 30c69c5

Browse files
committed
Add NestedExceptionsInterface interface for exceptions that hold multiple individual exceptions
1 parent 7c833ee commit 30c69c5

File tree

7 files changed

+92
-3
lines changed

7 files changed

+92
-3
lines changed

UPGRADE-6.4.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Messenger
112112
---------
113113

114114
* Deprecate `StopWorkerOnSignalsListener` in favor of using the `SignalableCommandInterface`
115+
* Deprecate `HandlerFailedException::getNestedExceptionOfClass` which is replaced by `HandlerFailedException::getWrappedExceptions`
115116

116117
MonologBridge
117118
-------------

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Deprecate `StopWorkerOnSignalsListener` in favor of using the `SignalableCommandInterface`
88
* Add `HandlerDescriptor::getOptions`
9+
* Add `NestedExceptionsInterface` interface for exceptions that hold multiple individual exceptions
910

1011
6.3
1112
---

src/Symfony/Component/Messenger/Exception/DelayedMessageHandlingException.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
*
1818
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
1919
*/
20-
class DelayedMessageHandlingException extends RuntimeException
20+
class DelayedMessageHandlingException extends RuntimeException implements NestedExceptionsInterface
2121
{
22+
use NestedExceptionsTrait;
23+
2224
private array $exceptions;
2325

2426
public function __construct(array $exceptions)

src/Symfony/Component/Messenger/Exception/HandlerFailedException.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313

1414
use Symfony\Component\Messenger\Envelope;
1515

16-
class HandlerFailedException extends RuntimeException
16+
class HandlerFailedException extends RuntimeException implements NestedExceptionsInterface
1717
{
18+
use NestedExceptionsTrait;
19+
1820
private array $exceptions;
1921
private Envelope $envelope;
2022

@@ -55,6 +57,8 @@ public function getNestedExceptions(): array
5557

5658
public function getNestedExceptionOfClass(string $exceptionClassName): array
5759
{
60+
trigger_deprecation('symfony/messenger', '6.4', 'The "%s()" method is deprecated, use "%s::getWrappedExceptions" instead.', __METHOD__, self::class);
61+
5862
return array_values(
5963
array_filter(
6064
$this->exceptions,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Exception;
13+
14+
/**
15+
* Exception that holds multiple exceptions thrown by one or more handlers and/or messages.
16+
*
17+
* @author Jeroen <https://github.com/Jeroeny>
18+
*/
19+
interface NestedExceptionsInterface extends \Throwable
20+
{
21+
/**
22+
* @return \Throwable[]
23+
*/
24+
public function getWrappedExceptions(string $class = null, bool $recursive = false): array;
25+
}
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 the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Exception;
13+
14+
/**
15+
* @author Jeroen <https://github.com/Jeroeny>
16+
*/
17+
trait NestedExceptionsTrait
18+
{
19+
/**
20+
* @return \Throwable[]
21+
*/
22+
public function getWrappedExceptions(string $class = null, bool $recursive = false): array
23+
{
24+
return $recursive ? iterator_to_array($this->getWrappedExceptionsRecursively($class, $this->exceptions), false) : $this->exceptions;
25+
}
26+
27+
/**
28+
* @param iterable<\Throwable>
29+
*
30+
* @return \Traversable<\Throwable>
31+
*/
32+
private function getWrappedExceptionsRecursively(?string $class, iterable $exceptions): \Traversable
33+
{
34+
foreach ($exceptions as $exception) {
35+
if ($exception instanceof NestedExceptionsInterface) {
36+
yield from $this->getWrappedExceptionsRecursively($class, $exception->getWrappedExceptions());
37+
38+
return;
39+
}
40+
41+
yield $exception;
42+
}
43+
}
44+
}

src/Symfony/Component/Messenger/Tests/Exception/HandlerFailedExceptionTest.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Messenger\Envelope;
16+
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
1617
use Symfony\Component\Messenger\Exception\HandlerFailedException;
1718
use Symfony\Component\Messenger\Tests\Fixtures\MyOwnChildException;
1819
use Symfony\Component\Messenger\Tests\Fixtures\MyOwnException;
@@ -32,7 +33,7 @@ public function __construct()
3233
};
3334

3435
$handlerException = new HandlerFailedException($envelope, [$exception]);
35-
$originalException = $handlerException->getNestedExceptions()[0];
36+
$originalException = $handlerException->getWrappedExceptions()[0];
3637

3738
$this->assertIsInt($handlerException->getCode(), 'Exception codes must converts to int');
3839
$this->assertSame(0, $handlerException->getCode(), 'String code (HY000) converted to int must be 0');
@@ -66,4 +67,15 @@ public function testThatNestedExceptionClassAreNotFoundIfNotPresent()
6667
$handlerException = new HandlerFailedException($envelope, [$exception]);
6768
$this->assertCount(0, $handlerException->getNestedExceptionOfClass(MyOwnException::class));
6869
}
70+
71+
public function testThatNestedExceptionsRecursive()
72+
{
73+
$envelope = new Envelope(new \stdClass());
74+
$exception1 = new \LogicException();
75+
$exception2 = new MyOwnException('second');
76+
$exception3 = new MyOwnException('third');
77+
78+
$handlerException = new HandlerFailedException($envelope, [$exception1, $exception2, new DelayedMessageHandlingException([$exception3])]);
79+
$this->assertSame([$exception1, $exception2, $exception3], $handlerException->getWrappedExceptions(recursive: true));
80+
}
6981
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy