Skip to content

Commit 03e3258

Browse files
committed
Merge branch 'feature/inital-version'
2 parents 6493e2b + a50217b commit 03e3258

16 files changed

+1645
-1
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor/
2+
/.idea/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\DependencyInjection;
5+
6+
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\Extension\Extension;
9+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
10+
use Symfony\Component\Config\FileLocator;
11+
12+
class HalloVerdenHttpExceptionsExtension extends Extension {
13+
14+
/**
15+
* @inheritDoc
16+
* @throws \Exception
17+
*/
18+
public function load(array $configs, ContainerBuilder $container) {
19+
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
20+
$loader->load('services.yaml');
21+
}
22+
23+
}

EventListener/ExceptionListener.php

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\EventListener;
5+
6+
use HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionConverterServiceInterface;
7+
use HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionLogServiceInterface;
8+
use HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionResponseServiceInterface;
9+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10+
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
11+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
12+
use Symfony\Component\HttpKernel\KernelEvents;
13+
14+
class ExceptionListener implements EventSubscriberInterface {
15+
16+
/**
17+
* @var ExceptionConverterServiceInterface
18+
*/
19+
private $exceptionConverterService;
20+
21+
/**
22+
* @var ExceptionLogServiceInterface
23+
*/
24+
private $logExceptionService;
25+
26+
/**
27+
* @var ExceptionResponseServiceInterface
28+
*/
29+
private $exceptionResponseService;
30+
31+
/**
32+
* ExceptionListener constructor.
33+
*
34+
* @param ExceptionConverterServiceInterface $exceptionConverterService
35+
* @param ExceptionLogServiceInterface $logExceptionService
36+
* @param ExceptionResponseServiceInterface $exceptionResponseService
37+
*/
38+
public function __construct(ExceptionConverterServiceInterface $exceptionConverterService,
39+
ExceptionLogServiceInterface $logExceptionService,
40+
ExceptionResponseServiceInterface $exceptionResponseService) {
41+
$this->exceptionConverterService = $exceptionConverterService;
42+
$this->logExceptionService = $logExceptionService;
43+
$this->exceptionResponseService = $exceptionResponseService;
44+
}
45+
46+
/**
47+
* @param ExceptionEvent $event
48+
*/
49+
public function convertKernelException(ExceptionEvent $event) {
50+
$throwable = $event->getThrowable();
51+
52+
if (!$throwable instanceof HttpExceptionInterface) {
53+
$event->setThrowable($this->exceptionConverterService->createHttpExceptionFromThrowable($event->getThrowable()));
54+
}
55+
}
56+
57+
/**
58+
* @param ExceptionEvent $event
59+
*/
60+
public function logKernelException(ExceptionEvent $event) {
61+
$exception = $event->getThrowable();
62+
if (!$exception instanceof HttpExceptionInterface) {
63+
return;
64+
}
65+
66+
$this->logExceptionService->logHttpException($exception);
67+
}
68+
69+
70+
/**
71+
* @param ExceptionEvent $event
72+
*/
73+
public function onKernelException(ExceptionEvent $event) {
74+
$exception = $event->getThrowable();
75+
if (!$exception instanceof HttpExceptionInterface) {
76+
return;
77+
}
78+
79+
$event->setResponse($this->exceptionResponseService->createResponseFromHttpException($exception));
80+
}
81+
82+
/**
83+
* @inheritDoc
84+
*/
85+
public static function getSubscribedEvents() {
86+
return array(
87+
KernelEvents::EXCEPTION => [
88+
['convertKernelException', 2048],
89+
['logKernelException', 1024],
90+
['onKernelException', 32]
91+
],
92+
);
93+
}
94+
}

HalloVerdenHttpExceptionsBundle.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle;
5+
6+
7+
use Symfony\Component\HttpKernel\Bundle\Bundle;
8+
9+
class HalloVerdenHttpExceptionsBundle extends Bundle {
10+
11+
}

Helpers/FlattenExceptionHelper.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\Helpers;
5+
6+
7+
use Symfony\Component\ErrorHandler\Exception\FlattenException;
8+
9+
/**
10+
* Class FlattenExceptionHelper
11+
*
12+
* Holds a copy of flatten exception to avoid running create more than once.
13+
*
14+
* @package HalloVerden\HttpExceptionsBundle\Helpers
15+
*/
16+
class FlattenExceptionHelper extends FlattenException {
17+
18+
/**
19+
* @var array<int, FlattenException>
20+
*/
21+
private static $exceptions = [];
22+
23+
/**
24+
* @inheritDoc
25+
*/
26+
public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): FlattenException {
27+
$id = \spl_object_id($exception);
28+
29+
if (isset(static::$exceptions[$id])) {
30+
return static::$exceptions[$id];
31+
}
32+
33+
return static::$exceptions[$id] = parent::createFromThrowable($exception, $statusCode, $headers);
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\Interfaces\Services;
5+
6+
7+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
8+
9+
interface ExceptionConverterServiceInterface {
10+
11+
/**
12+
* @param \Throwable $throwable
13+
*
14+
* @return HttpExceptionInterface
15+
*/
16+
public function createHttpExceptionFromThrowable(\Throwable $throwable): HttpExceptionInterface;
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\Interfaces\Services;
5+
6+
7+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
8+
9+
interface ExceptionLogServiceInterface {
10+
11+
/**
12+
* @param HttpExceptionInterface $exception
13+
*/
14+
public function logHttpException(HttpExceptionInterface $exception): void;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\Interfaces\Services;
5+
6+
7+
use Symfony\Component\HttpFoundation\Response;
8+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
9+
10+
interface ExceptionResponseServiceInterface {
11+
12+
/**
13+
* @param HttpExceptionInterface $exception
14+
*
15+
* @return Response
16+
*/
17+
public function createResponseFromHttpException(HttpExceptionInterface $exception): Response;
18+
}

README.md

+44-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,44 @@
1-
# symfony-http-exceptions-bundle
1+
HalloVerdenHttpExceptionsBundle
2+
==============================
3+
4+
Installation
5+
============
6+
7+
Make sure Composer is installed globally, as explained in the
8+
[installation chapter](https://getcomposer.org/doc/00-intro.md)
9+
of the Composer documentation.
10+
11+
Applications that use Symfony Flex
12+
----------------------------------
13+
14+
Open a command console, enter your project directory and execute:
15+
16+
```console
17+
$ composer require halloverden/symfony-http-exceptions-bundle
18+
```
19+
20+
Applications that don't use Symfony Flex
21+
----------------------------------------
22+
23+
### Step 1: Download the Bundle
24+
25+
Open a command console, enter your project directory and execute the
26+
following command to download the latest stable version of this bundle:
27+
28+
```console
29+
$ composer require halloverden/symfony-http-exceptions-bundle
30+
```
31+
32+
### Step 2: Enable the Bundle
33+
34+
Then, enable the bundle by adding it to the list of registered bundles
35+
in the `config/bundles.php` file of your project:
36+
37+
```php
38+
// config/bundles.php
39+
40+
return [
41+
// ...
42+
HalloVerden\HttpExceptionsBundle\HalloVerdenHttpExceptionsBundle::class => ['all' => true],
43+
];
44+
```

Resources/config/services.yaml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
services:
2+
HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionConverterServiceInterface:
3+
class: HalloVerden\HttpExceptionsBundle\Services\ExceptionConverterService
4+
5+
HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionLogServiceInterface:
6+
class: HalloVerden\HttpExceptionsBundle\Services\ExceptionLogService
7+
calls:
8+
- ['setLogger', ['@?logger']]
9+
10+
HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionResponseServiceInterface:
11+
class: HalloVerden\HttpExceptionsBundle\Services\ExceptionResponseService
12+
arguments:
13+
$debug: '%kernel.debug%'
14+
15+
HalloVerden\HttpExceptionsBundle\EventListener\ExceptionListener:
16+
tags:
17+
- {name: 'kernel.event_subscriber'}
18+
arguments:
19+
$exceptionConverterService: '@HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionConverterServiceInterface'
20+
$logExceptionService: '@HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionLogServiceInterface'
21+
$exceptionResponseService: '@HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionResponseServiceInterface'

Resources/doc/index.rst

Whitespace-only changes.
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\Services;
5+
6+
7+
use HalloVerden\HttpExceptions\Http\HttpException;
8+
use HalloVerden\HttpExceptions\InternalServerErrorException;
9+
use HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionConverterServiceInterface;
10+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
11+
12+
class ExceptionConverterService implements ExceptionConverterServiceInterface {
13+
const ERROR_UNKNOWN = 'UNKNOWN_ERROR';
14+
15+
/**
16+
* @param \Throwable $throwable
17+
*
18+
* @return HttpExceptionInterface
19+
*/
20+
public function createHttpExceptionFromThrowable(\Throwable $throwable): HttpExceptionInterface {
21+
if ($throwable instanceof HttpException) {
22+
return $throwable;
23+
}
24+
25+
return new InternalServerErrorException(self::ERROR_UNKNOWN, $throwable);
26+
}
27+
28+
}

Services/ExceptionLogService.php

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
4+
namespace HalloVerden\HttpExceptionsBundle\Services;
5+
6+
7+
use HalloVerden\HttpExceptionsBundle\Helpers\FlattenExceptionHelper;
8+
use HalloVerden\HttpExceptionsBundle\Interfaces\Services\ExceptionLogServiceInterface;
9+
use Psr\Log\LoggerAwareTrait;
10+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
11+
12+
class ExceptionLogService implements ExceptionLogServiceInterface {
13+
use LoggerAwareTrait;
14+
15+
const MESSAGE_ERROR = 'InternalServerError';
16+
const MESSAGE_INFO = 'Exception was thrown';
17+
18+
/**
19+
* @param HttpExceptionInterface $exception
20+
*/
21+
public function logHttpException(HttpExceptionInterface $exception): void {
22+
if (!$this->logger) {
23+
return;
24+
}
25+
26+
$context = FlattenExceptionHelper::createFromThrowable($exception)->toArray();
27+
if ($exception->getStatusCode() >= 500) {
28+
$this->logger->error(self::MESSAGE_ERROR, $context);
29+
} else {
30+
$this->logger->info(self::MESSAGE_INFO, $context);
31+
}
32+
}
33+
34+
}

0 commit comments

Comments
 (0)