Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

## Installation 📥

1. Install via composer
1. Install via composer:

```sh
composer require phphd/exception-toolkit
```

2. In case you are using symfony, enable the bundle in the `bundles.php`
2. If you are using Symfony, enable the bundle in the `bundles.php`

```php
PhPhD\ExceptionToolkit\Bundle\PhdExceptionToolkitBundle::class => ['all' => true],
Expand All @@ -31,7 +31,6 @@ Allows you to unwrap composite exceptions and get the atomic errors you are inte
use PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper;

/** @var ExceptionUnwrapper $unwrapper */
$unwrapper = getUnwrapper();

$compositeException = new CompositeException([
new InvalidEmailException(),
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
"php": ">=8.1"
},
"conflict": {
"php": ">=9.0",
"symfony/http-kernel": "<6.0 || >8.4",
"symfony/dependency-injection": "<6.2 || >8.4" ,
"symfony/config": "<6.0 || >8.4",
"symfony/messenger": ">8.4",
"symfony/deprecation-contracts": "<2.5",
"amphp/amp": ">=4.0"
},
"require-dev": {
Expand Down
6 changes: 6 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,11 @@
<include>
<directory>src</directory>
</include>
<exclude>
<directory>src/*/*/Tests</directory>
<directory>src/*/*/*/Tests</directory>
<directory suffix="Test.php">src</directory>
<directory suffix="services.php">src</directory>
</exclude>
</source>
</phpunit>
59 changes: 35 additions & 24 deletions src/Bundle/DependencyInjection/PhdExceptionToolkitExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,54 @@

namespace PhPhD\ExceptionToolkit\Bundle\DependencyInjection;

use Amp\CompositeException as AmpCompositeException;
use Exception;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Messenger\Exception\WrappedExceptionsInterface as MessengerCompositeException;
use Symfony\Component\DependencyInjection\Extension\AbstractExtension;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

use function class_exists;
use function interface_exists;
use function array_keys;
use function array_map;

final class PhdExceptionToolkitExtension extends Extension
final class PhdExceptionToolkitExtension extends AbstractExtension
{
public const ALIAS = 'phd_exception_toolkit';

/**
* @param array<array-key,mixed> $configs
*
* @override
*
* @throws Exception
* @param array<string,mixed> $parameters required by {@see \Symfony\Component\DependencyInjection\Extension\ExtensionTrait::executeConfiguratorCallback()}:
* - kernel.environment
* - kernel.build_dir
*/
public function load(array $configs, ContainerBuilder $container): void
public static function getContainer(array $parameters): ContainerBuilder
{
/** @var ?string $env */
$env = $container->getParameter('kernel.environment');
$container = new ContainerBuilder();

$container->setResourceTracking(false);
$container->getCompilerPassConfig()->setBeforeOptimizationPasses([]);
$container->getCompilerPassConfig()->setOptimizationPasses([]);
$container->getCompilerPassConfig()->setRemovingPasses([]);
$container->getCompilerPassConfig()->setAfterRemovingPasses([]);

$container->registerExtension($extension = new self());
$container->loadFromExtension($extension->getAlias());

$container->addCompilerPass(new DecoratorServicePass(), PassConfig::TYPE_OPTIMIZE);

$loader = new YamlFileLoader($container, new FileLocator(), $env);
$loader->load(__DIR__.'/../../Unwrapper/services.yaml');
array_map($container->setParameter(...), array_keys($parameters), $parameters); // @phpstan-ignore argument.type

if (class_exists(AmpCompositeException::class)) {
$loader->load(__DIR__.'/../../Unwrapper/Amp/services.yaml');
}
return $container;
}

if (interface_exists(MessengerCompositeException::class)) {
$loader->load(__DIR__.'/../../Unwrapper/Messenger/services.yaml');
}
/**
* @param array<array-key,mixed> $config
*
* @throws Exception
*/
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$container->import(__DIR__.'/../../**/services.php');
$container->import(__DIR__.'/../../**/services.yaml');
}

/** @override */
Expand Down
29 changes: 29 additions & 0 deletions src/Unwrapper/Amp/services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace PhPhD\ExceptionToolkit\Unwrapper\Amp;

use Amp\CompositeException as AmpCompositeException;
use PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

use function class_exists;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $containerConfigurator): void {
if (!class_exists(AmpCompositeException::class)) {
return;
}

$services = $containerConfigurator->services();

$services
->set('phd_exception_toolkit.exception_unwrapper.amp', AmpExceptionUnwrapper::class)
->decorate('phd_exception_toolkit.exception_unwrapper.stack')
->args([
service('.inner'),
service(ExceptionUnwrapper::class),
])
;
};
7 changes: 0 additions & 7 deletions src/Unwrapper/Amp/services.yaml

This file was deleted.

29 changes: 29 additions & 0 deletions src/Unwrapper/Messenger/services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace PhPhD\ExceptionToolkit\Unwrapper\Messenger;

use PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\Messenger\Exception\WrappedExceptionsInterface as MessengerCompositeException;

use function interface_exists;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $containerConfigurator): void {
if (!interface_exists(MessengerCompositeException::class)) {
return;
}

$services = $containerConfigurator->services();

$services
->set('phd_exception_toolkit.exception_unwrapper.messenger', MessengerExceptionUnwrapper::class)
->decorate('phd_exception_toolkit.exception_unwrapper.stack')
->args([
service('.inner'),
service(ExceptionUnwrapper::class),
])
;
};
7 changes: 0 additions & 7 deletions src/Unwrapper/Messenger/services.yaml

This file was deleted.

21 changes: 21 additions & 0 deletions src/Unwrapper/services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace PhPhD\ExceptionToolkit\Unwrapper\Amp;

use PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper;
use PhPhD\ExceptionToolkit\Unwrapper\PassThroughExceptionUnwrapper;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();

$services->alias('phd_exception_toolkit.exception_unwrapper', ExceptionUnwrapper::class);

// Stack is used to create a chain of decorated services.
// When adding new unwrapper, you should decorate this service:
$services
->set('phd_exception_toolkit.exception_unwrapper.stack', PassThroughExceptionUnwrapper::class)
;
};
6 changes: 2 additions & 4 deletions src/Unwrapper/services.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
services:
phd_exception_toolkit.exception_unwrapper:
PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper:
public: true
class: PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper
factory:
- !service_locator
stack: '@phd_exception_toolkit.exception_unwrapper.stack'
- get
arguments: [ stack ]
lazy: true

phd_exception_toolkit.exception_unwrapper.stack:
class: PhPhD\ExceptionToolkit\Unwrapper\PassThroughExceptionUnwrapper
2 changes: 1 addition & 1 deletion tests/Bundle/Compiler/TestServicesCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ final class TestServicesCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
$container->getDefinition('phd_exception_toolkit.exception_unwrapper')->setPublic(true);
$container->getAlias('phd_exception_toolkit.exception_unwrapper')->setPublic(true);
}
}
26 changes: 10 additions & 16 deletions tests/Unwrapper/ExceptionUnwrapperUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@

use Amp\CompositeException;
use Exception;
use PhPhD\ExceptionToolkit\Unwrapper\Amp\AmpExceptionUnwrapper;
use PhPhD\ExceptionToolkit\Bundle\DependencyInjection\PhdExceptionToolkitExtension;
use PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper;
use PhPhD\ExceptionToolkit\Unwrapper\Messenger\MessengerExceptionUnwrapper;
use PhPhD\ExceptionToolkit\Unwrapper\PassThroughExceptionUnwrapper;
use PHPUnit\Framework\TestCase;
use stdClass;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\HandlerFailedException;
use Throwable;

/**
* @covers \PhPhD\ExceptionToolkit\Bundle\DependencyInjection\PhdExceptionToolkitExtension
* @covers \PhPhD\ExceptionToolkit\Unwrapper\PassThroughExceptionUnwrapper
* @covers \PhPhD\ExceptionToolkit\Unwrapper\Amp\AmpExceptionUnwrapper
* @covers \PhPhD\ExceptionToolkit\Unwrapper\Messenger\MessengerExceptionUnwrapper
Expand All @@ -31,19 +29,15 @@ protected function setUp(): void
{
parent::setUp();

$this->exceptionUnwrapper = self::createStub(ExceptionUnwrapper::class);
$container = PhdExceptionToolkitExtension::getContainer([
'kernel.environment' => 'test',
'kernel.build_dir' => __DIR__.'/var',
]);
$container->compile();

$stackUnwrapper = new MessengerExceptionUnwrapper(
new AmpExceptionUnwrapper(
new PassThroughExceptionUnwrapper(),
$this->exceptionUnwrapper,
),
$this->exceptionUnwrapper,
);

$this->exceptionUnwrapper->method('unwrap')
->willReturnCallback(static fn (Throwable $exception): array => $stackUnwrapper->unwrap($exception))
;
/** @var ExceptionUnwrapper $unwrapper */
$unwrapper = $container->get(ExceptionUnwrapper::class);
$this->exceptionUnwrapper = $unwrapper;
}

public function testAtomicExceptionIsNotUnwrapped(): void
Expand Down