Completed
Push — master ( 3a58ae...412d43 )
by Christian
08:50 queued 33s
created

ExceptionController::getAndCleanOutputBuffering()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 1
cts 1
cp 1
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of the FOSRestBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.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 FOS\RestBundle\Controller;
13
14
use FOS\RestBundle\Exception\FlattenException as FosFlattenException;
15
use FOS\RestBundle\Util\ExceptionValueMap;
16
use FOS\RestBundle\View\View;
17
use FOS\RestBundle\View\ViewHandlerInterface;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\ErrorHandler\Exception\FlattenException;
21
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
22
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
23
24
/**
25
 * Custom ExceptionController that uses the view layer and supports HTTP response status code mapping.
26
 */
27
class ExceptionController
28
{
29
    /**
30
     * @var ViewHandlerInterface
31
     */
32
    private $viewHandler;
33
34
    /**
35
     * @var ExceptionValueMap
36
     */
37
    private $exceptionCodes;
38
39
    /**
40
     * @var bool
41
     */
42
    private $showException;
43 9
44
    public function __construct(
45
        ViewHandlerInterface $viewHandler,
46
        ExceptionValueMap $exceptionCodes,
47
        $showException
48 9
    ) {
49 9
        $this->viewHandler = $viewHandler;
50 9
        $this->exceptionCodes = $exceptionCodes;
51 9
        $this->showException = $showException;
52
    }
53
54
    /**
55
     * Converts an Exception to a Response.
56
     *
57
     * @param Request                   $request
58
     * @param \Exception|\Throwable     $exception
59
     * @param DebugLoggerInterface|null $logger
60
     *
61
     * @throws \InvalidArgumentException
62
     *
63
     * @return Response
64 9
     */
65
    public function showAction(Request $request, $exception, DebugLoggerInterface $logger = null)
0 ignored issues
show
Unused Code introduced by
The parameter $logger is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
66 9
    {
67 9
        $currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
0 ignored issues
show
Unused Code introduced by
$currentContent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
68 9
        $code = $this->getStatusCode($exception);
0 ignored issues
show
Compatibility introduced by
$exception of type object<Throwable> is not a sub-type of object<Exception>. It seems like you assume a concrete implementation of the interface Throwable to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
69
70 9
        $view = $this->createView($exception, $code, $request, $this->showException);
0 ignored issues
show
Compatibility introduced by
$exception of type object<Throwable> is not a sub-type of object<Exception>. It seems like you assume a concrete implementation of the interface Throwable to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
71 9
        $response = $this->viewHandler->handle($view);
72
73 9
        return $response;
74
    }
75
76
    /**
77
     * @param \Exception $exception
78
     * @param int        $code
79
     * @param Request    $request
80
     * @param bool       $showException
81
     *
82
     * @return View
83
     */
84
    protected function createView(\Exception $exception, $code, Request $request, $showException)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $showException is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
85 9
    {
86
        return $this->createViewFromThrowable($exception, $code, $templateData);
0 ignored issues
show
Bug introduced by
The variable $templateData does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
87 9
    }
88 9
89 9
    /**
90
     * Determines the status code to use for the response.
91 9
     *
92
     * @param \Exception $exception
93
     *
94
     * @return int
95
     */
96
    protected function getStatusCode(\Exception $exception)
97
    {
98
        return $this->getStatusCodeFromThrowable($exception);
99
    }
100
101 9
    private function createViewFromThrowable(\Throwable $exception, $code, array $templateData): View
0 ignored issues
show
Unused Code introduced by
The parameter $templateData is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
102
    {
103
        $view = new View($exception, $code, $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : []);
104 9
105
        return $view;
106
    }
107
108
    /**
109 9
     * Determines the status code to use for the response.
110 1
     *
111
     * @param \Exception $exception
112
     *
113 8
     * @return int
114
     */
115
    protected function getStatusCode(\Exception $exception)
116
    {
117
        // If matched
118
        if ($statusCode = $this->exceptionCodes->resolveException($exception)) {
119
            return $statusCode;
120
        }
121
122
        // Otherwise, default
123
        if ($exception instanceof HttpExceptionInterface) {
124
            return $exception->getStatusCode();
125
        }
126 9
127
        return 500;
128
    }
129 9
130 9
    /**
131 9
     * Gets and cleans any content that was already outputted.
132 9
     *
133 9
     * This code comes from Symfony and should be synchronized on a regular basis
134 9
     * see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
135 9
     *
136
     * @return string
137
     */
138
    private function getAndCleanOutputBuffering($startObLevel)
139
    {
140
        if (ob_get_level() <= $startObLevel) {
141
            return '';
142
        }
143
        Response::closeOutputBuffers($startObLevel + 1, true);
144
145
        return ob_get_clean();
146 9
    }
147
148 9
    /**
149 9
     * Determines the status code to use for the response.
150
     *
151
     * @param \Throwable $exception
152
     *
153
     * @return int
154
     */
155
    private function getStatusCodeFromThrowable(\Throwable $exception)
156
    {
157
        // If matched
158
        if ($statusCode = $this->exceptionCodes->resolveThrowable($exception)) {
159
            return $statusCode;
160
        }
161
162
        // Otherwise, default
163
        if ($exception instanceof HttpExceptionInterface) {
164
            return $exception->getStatusCode();
165
        }
166
167
        return 500;
168
    }
169
}
170