Completed
Push — master ( 8c5203...c6433c )
by Gerrit
23:20
created

executeInnerControllerSafely()   C

Complexity

Conditions 10
Paths 20

Size

Total Lines 68

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 10

Importance

Changes 0
Metric Value
dl 0
loc 68
c 0
b 0
f 0
ccs 31
cts 31
cp 1
rs 6.8315
cc 10
nc 20
nop 1
crap 10

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
 * Copyright (C) 2018 Gerrit Addiks.
4
 * This package (including this file) was released under the terms of the GPL-3.0.
5
 * You should have received a copy of the GNU General Public License along with this program.
6
 * If not, see <http://www.gnu.org/licenses/> or send me a mail so i can send you a copy.
7
 *
8
 * @license GPL-3.0
9
 *
10
 * @author Gerrit Addiks <[email protected]>
11
 */
12
13
namespace Addiks\SymfonyGenerics\Controllers;
14
15
use Addiks\SymfonyGenerics\Controllers\ControllerHelperInterface;
16
use Webmozart\Assert\Assert;
17
use Exception;
18
use Throwable;
19
use Symfony\Component\HttpFoundation\Response;
20
use ErrorException;
21
use Addiks\SymfonyGenerics\Services\ArgumentCompilerInterface;
22
use Symfony\Component\HttpFoundation\Request;
23
24
final class GenericExceptionResponseController
25
{
26
27
    /**
28
     * @var ControllerHelperInterface
29
     */
30
    private $controllerHelper;
31
32
    /**
33
     * @var ArgumentCompilerInterface
34
     */
35
    private $argumentBuilder;
36
37
    /**
38
     * @var object
39
     */
40
    private $innerController;
41
42
    /**
43
     * @var string
44
     */
45
    private $innerControllerMethod;
46
47
    /**
48
     * @var string|null
49
     */
50
    private $successResponse;
51
52
    /**
53
     * @var int
54
     */
55
    private $successResponseCode;
56
57
    /**
58
     * @var string|null
59
     */
60
    private $successFlashMessage;
61
62
    /**
63
     * @var array<string, array<string, mixed>>
64
     */
65
    private $exceptionResponses = array();
66
67
    /**
68
     * @param object $innerController
0 ignored issues
show
Bug introduced by
There is no parameter named $innerController. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
69
     */
70 12
    public function __construct(
71
        ControllerHelperInterface $controllerHelper,
72
        ArgumentCompilerInterface $argumentBuilder,
73
        array $options
74
    ) {
75
        /** @var int $defaultResponseCode */
76 12
        $defaultResponseCode = 200;
77
78
        /** @var array<string, mixed> $defaults */
79
        $defaults = array(
80 12
            'exception-responses' => [],
81
            'success-response' => null,
82 12
            'success-response-code' => $defaultResponseCode,
83
            'success-flash-message' => null,
84
        );
85
86
        /** @var mixed $options */
87 12
        $options = array_merge($defaults, $options);
88
89 12
        Assert::null($this->controllerHelper);
90 12
        Assert::true(is_object($options['inner-controller']));
91
92 11
        $this->controllerHelper = $controllerHelper;
93 11
        $this->argumentBuilder = $argumentBuilder;
94 11
        $this->innerController = $options['inner-controller'];
95 11
        $this->innerControllerMethod = $options['inner-controller-method'];
96 11
        $this->successResponse = $options['success-response'];
97 11
        $this->successResponseCode = $options['success-response-code'];
98 11
        $this->successFlashMessage = $options['success-flash-message'];
99
100 11
        foreach ($options['exception-responses'] as $exceptionClass => $responseData) {
101
            /** @var array<string, mixed> $responseData */
102
103 4
            Assert::true(
104 4
                is_subclass_of($exceptionClass, Exception::class) ||
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Exception::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
105 4
                is_subclass_of($exceptionClass, Throwable::class)
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Throwable::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
106
            );
107
108 3
            $responseData = array_merge([
109 3
                'message' => '', # empty => exception message used
110
                'code' => '500',
111
                'flash-type' => '', # empty => no message triggered
112
                'flash-message' => '', # empty => exception message used
113
                'redirect-route' => null,
114
                'redirect-route-parameters' => [],
115 3
            ], $responseData);
116
117 3
            $this->exceptionResponses[$exceptionClass] = $responseData;
118
        }
119 10
    }
120
121 9
    public function executeInnerControllerSafely(Request $request): Response
122
    {
123
        /** @var Response|null $response */
124 9
        $response = null;
125
126
        /** @var Response|null $innerResponse */
127 9
        $innerResponse = null;
128
129
        try {
130
            /** @var array<int, mixed> $arguments */
131 9
            $arguments = array();# TODO
132
133 9
            $innerResponse = call_user_func([$this->innerController, $this->innerControllerMethod], $arguments);
134
135 5
            Assert::isInstanceOf($innerResponse, Response::class, "Controller did not return an Response object!");
136
137 4
            if (!is_null($this->successFlashMessage)) {
138 1
                $this->controllerHelper->addFlashMessage($this->successFlashMessage, "success");
139
            }
140
141 4
            if (!is_null($this->successResponse)) {
142 2
                $response = new Response($this->successResponse, $this->successResponseCode);
143
144
            } else {
145 4
                $response = $innerResponse;
146
            }
147
148 5
        } catch (Throwable $exception) {
149 5
            $this->controllerHelper->handleException($exception);
150
151 5
            foreach ($this->exceptionResponses as $exceptionClass => $responseData) {
152 3
                if (is_a($exception, $exceptionClass)) {
153
                    /** @var string $responseMessage */
154 3
                    $responseMessage = $responseData['message'];
155
156 3
                    if (empty($responseMessage)) {
157 3
                        $responseMessage = $exception->getMessage();
158
                    }
159
160 3
                    if (!empty($responseData['flash-type'])) {
161
                        /** @var string $flashMessage */
162 2
                        $flashMessage = sprintf($responseData['flash-message'], $exception->getMessage());
163
164 2
                        $this->controllerHelper->addFlashMessage($flashMessage, $responseData['flash-type']);
165
                    }
166
167 3
                    if (!empty($responseData['redirect-route'])) {
168 1
                        $response = $this->controllerHelper->redirectToRoute(
169 1
                            $responseData['redirect-route'],
170 1
                            $this->argumentBuilder->buildRouteArguments(
171 1
                                $responseData['redirect-route-parameters'],
172 1
                                $request
173
                            )
174
                        );
175
176
                    } else {
177 3
                        $response = new Response($responseMessage, $responseData['code']);
178
                    }
179
                }
180
            }
181
182 5
            if (is_null($response)) {
183 2
                throw $exception;
184
            }
185
        }
186
187 7
        return $response;
188
    }
189
190
}
191