diff --git a/README.md b/README.md
index b143b62..b29b17d 100644
--- a/README.md
+++ b/README.md
@@ -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],
@@ -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(),
diff --git a/composer.json b/composer.json
index c0253a2..6e15c35 100644
--- a/composer.json
+++ b/composer.json
@@ -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": {
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index a7764c4..35cd868 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -21,5 +21,11 @@
src
+
+ src/*/*/Tests
+ src/*/*/*/Tests
+ src
+ src
+
diff --git a/src/Bundle/DependencyInjection/PhdExceptionToolkitExtension.php b/src/Bundle/DependencyInjection/PhdExceptionToolkitExtension.php
index 9caaf72..4d12b12 100644
--- a/src/Bundle/DependencyInjection/PhdExceptionToolkitExtension.php
+++ b/src/Bundle/DependencyInjection/PhdExceptionToolkitExtension.php
@@ -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 $configs
- *
- * @override
- *
- * @throws Exception
+ * @param array $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 $config
+ *
+ * @throws Exception
+ */
+ public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
+ {
+ $container->import(__DIR__.'/../../**/services.php');
+ $container->import(__DIR__.'/../../**/services.yaml');
}
/** @override */
diff --git a/src/Unwrapper/Amp/services.php b/src/Unwrapper/Amp/services.php
new file mode 100644
index 0000000..2c597ae
--- /dev/null
+++ b/src/Unwrapper/Amp/services.php
@@ -0,0 +1,29 @@
+services();
+
+ $services
+ ->set('phd_exception_toolkit.exception_unwrapper.amp', AmpExceptionUnwrapper::class)
+ ->decorate('phd_exception_toolkit.exception_unwrapper.stack')
+ ->args([
+ service('.inner'),
+ service(ExceptionUnwrapper::class),
+ ])
+ ;
+};
diff --git a/src/Unwrapper/Amp/services.yaml b/src/Unwrapper/Amp/services.yaml
deleted file mode 100644
index 903917b..0000000
--- a/src/Unwrapper/Amp/services.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
- phd_exception_toolkit.exception_unwrapper.amp:
- class: PhPhD\ExceptionToolkit\Unwrapper\Amp\AmpExceptionUnwrapper
- decorates: phd_exception_toolkit.exception_unwrapper.stack
- arguments:
- - '@.inner'
- - '@phd_exception_toolkit.exception_unwrapper'
diff --git a/src/Unwrapper/Messenger/services.php b/src/Unwrapper/Messenger/services.php
new file mode 100644
index 0000000..015257b
--- /dev/null
+++ b/src/Unwrapper/Messenger/services.php
@@ -0,0 +1,29 @@
+services();
+
+ $services
+ ->set('phd_exception_toolkit.exception_unwrapper.messenger', MessengerExceptionUnwrapper::class)
+ ->decorate('phd_exception_toolkit.exception_unwrapper.stack')
+ ->args([
+ service('.inner'),
+ service(ExceptionUnwrapper::class),
+ ])
+ ;
+};
diff --git a/src/Unwrapper/Messenger/services.yaml b/src/Unwrapper/Messenger/services.yaml
deleted file mode 100644
index 10c7918..0000000
--- a/src/Unwrapper/Messenger/services.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
- phd_exception_toolkit.exception_unwrapper.messenger:
- class: PhPhD\ExceptionToolkit\Unwrapper\Messenger\MessengerExceptionUnwrapper
- decorates: phd_exception_toolkit.exception_unwrapper.stack
- arguments:
- - '@.inner'
- - '@phd_exception_toolkit.exception_unwrapper'
diff --git a/src/Unwrapper/services.php b/src/Unwrapper/services.php
new file mode 100644
index 0000000..bb5c9ea
--- /dev/null
+++ b/src/Unwrapper/services.php
@@ -0,0 +1,21 @@
+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)
+ ;
+};
diff --git a/src/Unwrapper/services.yaml b/src/Unwrapper/services.yaml
index c385cbe..d605747 100644
--- a/src/Unwrapper/services.yaml
+++ b/src/Unwrapper/services.yaml
@@ -1,5 +1,6 @@
services:
- phd_exception_toolkit.exception_unwrapper:
+ PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper:
+ public: true
class: PhPhD\ExceptionToolkit\Unwrapper\ExceptionUnwrapper
factory:
- !service_locator
@@ -7,6 +8,3 @@ services:
- get
arguments: [ stack ]
lazy: true
-
- phd_exception_toolkit.exception_unwrapper.stack:
- class: PhPhD\ExceptionToolkit\Unwrapper\PassThroughExceptionUnwrapper
diff --git a/tests/Bundle/Compiler/TestServicesCompilerPass.php b/tests/Bundle/Compiler/TestServicesCompilerPass.php
index 6af8683..12fcd55 100644
--- a/tests/Bundle/Compiler/TestServicesCompilerPass.php
+++ b/tests/Bundle/Compiler/TestServicesCompilerPass.php
@@ -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);
}
}
diff --git a/tests/Unwrapper/ExceptionUnwrapperUnitTest.php b/tests/Unwrapper/ExceptionUnwrapperUnitTest.php
index fe28006..2a0ceab 100644
--- a/tests/Unwrapper/ExceptionUnwrapperUnitTest.php
+++ b/tests/Unwrapper/ExceptionUnwrapperUnitTest.php
@@ -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
@@ -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