Completed
Pull Request — master (#49)
by John
05:45
created

ExceptionListener::onKernelException()   C

Complexity

Conditions 13
Paths 187

Size

Total Lines 71
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 71
rs 5.133
cc 13
eloc 57
nc 187
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of the KleijnWeb\SwaggerBundle package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace KleijnWeb\SwaggerBundle\EventListener;
10
11
use KleijnWeb\SwaggerBundle\Exception\InvalidParametersException;
12
use KleijnWeb\SwaggerBundle\Response\VndValidationErrorFactory;
13
use KleijnWeb\SwaggerBundle\Response\VndErrorResponse;
14
use Psr\Log\LoggerInterface;
15
use Psr\Log\LogLevel;
16
use Ramsey\VndError\VndError;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
20
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
21
use Symfony\Component\Security\Core\Exception\AuthenticationException;
22
23
/**
24
 * @author John Kleijn <[email protected]>
25
 */
26
class ExceptionListener
27
{
28
    /**
29
     * @var LoggerInterface
30
     */
31
    private $logger;
32
33
    /**
34
     * @var VndValidationErrorFactory
35
     */
36
    private $validationErrorFactory;
37
38
    /**
39
     * @param VndValidationErrorFactory $errorFactory
40
     * @param LoggerInterface           $logger
41
     */
42
    public function __construct(VndValidationErrorFactory $errorFactory, LoggerInterface $logger)
43
    {
44
        $this->logger = $logger;
45
        $this->validationErrorFactory = $errorFactory;
46
    }
47
48
    /**
49
     * @param LoggerInterface $logger
50
     *
51
     * @return $this
52
     */
53
    public function setLogger(LoggerInterface $logger)
54
    {
55
        $this->logger = $logger;
56
57
        return $this;
58
    }
59
60
    /**
61
     * @param GetResponseForExceptionEvent $event
62
     */
63
    public function onKernelException(GetResponseForExceptionEvent $event)
64
    {
65
        $logRef = uniqid();
66
67
        try {
68
            $exception = $event->getException();
69
            if (!$exception instanceof \Exception) {
70
                throw new \LogicException("No exception in event");
71
            }
72
            $request = $event->getRequest();
73
            if (!$request instanceof Request) {
74
                throw new \LogicException("No request in event");
75
            }
76
            $code = $exception->getCode();
77
78
            if ($exception instanceof InvalidParametersException) {
79
                $severity = LogLevel::NOTICE;
80
                $statusCode = Response::HTTP_BAD_REQUEST;
81
                $vndError = $this->validationErrorFactory->create($request, $exception, $logRef);
82
            } else {
83
                if ($exception instanceof NotFoundHttpException) {
84
                    $statusCode = Response::HTTP_NOT_FOUND;
85
                    $severity = LogLevel::INFO;
86
                } else {
87
                    if ($exception instanceof AuthenticationException) {
88
                        $statusCode = Response::HTTP_UNAUTHORIZED;
89
                        $severity = LogLevel::WARNING;
90
                    } else {
91
                        $is3Digits = strlen($code) === 3;
92
                        $class = (int)substr($code, 0, 1);
93
                        if (!$is3Digits) {
94
                            $statusCode = Response::HTTP_INTERNAL_SERVER_ERROR;
95
                            $severity = LogLevel::CRITICAL;
96
                        } else {
97
                            switch ($class) {
98
                                case 4:
99
                                    $severity = LogLevel::NOTICE;
100
                                    $statusCode = Response::HTTP_BAD_REQUEST;
101
                                    break;
102
                                case 5:
103
                                    $statusCode = Response::HTTP_INTERNAL_SERVER_ERROR;
104
                                    $severity = LogLevel::ERROR;
105
                                    break;
106
                                default:
107
                                    $statusCode = Response::HTTP_INTERNAL_SERVER_ERROR;
108
                                    $severity = LogLevel::CRITICAL;
109
                            }
110
                        }
111
                    }
112
                }
113
                $message = Response::$statusTexts[$statusCode];
114
                $vndError = new VndError($message, $logRef);
115
                $vndError->addLink('help', $request->get('_resource'), ['title' => 'Error Information']);
116
                $vndError->addLink('about', $request->getUri(), ['title' => 'Error Information']);
117
            }
118
119
            $reference = $logRef ? " [logref $logRef]" : '';
120
            $event->setResponse(new VndErrorResponse($vndError, $statusCode));
121
            $this->logger->log($severity, "{$vndError->getMessage()}{$reference}: $exception");
122
        } catch (\PHPUnit_Framework_Exception  $e) {
123
            throw $e;
124
        } catch (\PHPUnit_Framework_Error  $e) {
125
            throw $e;
126
        } catch (\Exception $e) {
127
            // A simpler response where less can go wrong
128
            $message = "Error Handling Failure";
129
            $vndError = new VndError($message, $logRef);
130
            $this->logger->log(LogLevel::CRITICAL, "$message [logref $logRef]: $e");
131
            $event->setResponse(new VndErrorResponse($vndError, Response::HTTP_INTERNAL_SERVER_ERROR));
132
        }
133
    }
134
}
135