Completed
Push — master ( 8c5900...f74501 )
by Mat
06:09 queued 10s
created

RedirectCallback::getRedirect()   C

Complexity

Conditions 15
Paths 144

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 5.55
c 0
b 0
f 0
cc 15
nc 144
nop 2

How to fix   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
namespace LmcUser\Controller;
4
5
use Laminas\Http\PhpEnvironment\Request;
6
use Laminas\Http\PhpEnvironment\Response;
7
use Laminas\Mvc\Application;
8
use Laminas\Router\Exception;
9
use Laminas\Router\RouteInterface;
10
use LmcUser\Options\ModuleOptions;
11
12
/**
13
 * Builds a redirect response based on the current routing and parameters
14
 */
15
class RedirectCallback
16
{
17
    /**
18
     * @var RouteInterface
19
     */
20
    private $router;
21
22
    /**
23
     * @var Application
24
     */
25
    private $application;
26
27
    /**
28
     * @var ModuleOptions
29
     */
30
    private $options;
31
32
    /**
33
     * @param Application    $application
34
     * @param RouteInterface $router
35
     * @param ModuleOptions  $options
36
     */
37
    public function __construct(Application $application, RouteInterface $router, ModuleOptions $options)
38
    {
39
        $this->router = $router;
40
        $this->application = $application;
41
        $this->options = $options;
42
    }
43
44
    /**
45
     * @return Response
46
     */
47
    public function __invoke()
48
    {
49
        $routeMatch = $this->application->getMvcEvent()->getRouteMatch();
50
        $redirect = $this->getRedirect($routeMatch->getMatchedRouteName(), $this->getRedirectRouteFromRequest());
0 ignored issues
show
Bug introduced by
It seems like $this->getRedirectRouteFromRequest() targeting LmcUser\Controller\Redir...irectRouteFromRequest() can also be of type string; however, LmcUser\Controller\RedirectCallback::getRedirect() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
51
52
        $response = $this->application->getResponse();
53
        $response->getHeaders()->addHeaderLine('Location', $redirect);
54
        $response->setStatusCode(302);
55
        return $response;
56
    }
57
58
    /**
59
     * Return the redirect from param.
60
     * First checks GET then POST
61
     *
62
     * @return string|boolean
63
     */
64
    private function getRedirectRouteFromRequest()
65
    {
66
        $request  = $this->application->getRequest();
67
        $redirect = $request->getQuery('redirect');
68
        if ($redirect && ($this->routeMatched($redirect) || $this->routeExists($redirect))) {
69
            return $redirect;
70
        }
71
72
        $redirect = $request->getPost('redirect');
73
        if ($redirect && ($this->routeMatched($redirect) || $this->routeExists($redirect))) {
74
            return $redirect;
75
        }
76
77
        return false;
78
    }
79
80
    /**
81
     * @param  $route
82
     * @return bool
83
     */
84
    private function routeExists($route)
85
    {
86
        try {
87
            $this->router->assemble([], ['name' => $route]);
88
        } catch (Exception\RuntimeException $e) {
89
            return false;
90
        }
91
        return true;
92
    }
93
94
    /**
95
     * @param  string $route
96
     * @return bool
97
     */
98
    private function routeMatched(string $route): bool
99
    {
100
        $request = new Request();
101
        $request->setUri($route);
102
        return (! is_null($this->router->match($request)));
103
    }
104
105
    /**
106
     * Returns the url to redirect to based on current route.
107
     * If $redirect is set and the option to use redirect is set to true, it will return the $redirect url.
108
     *
109
     * @param  string $currentRoute
110
     * @param  bool   $redirect
111
     * @return mixed
112
     */
113
    private function getRedirect($currentRoute, $redirect = false)
114
    {
115
        $useRedirect = $this->options->getUseRedirectParameterIfPresent();
116
        $routeMatched = ($redirect && $this->routeMatched($redirect));
0 ignored issues
show
Documentation introduced by
$redirect is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
117
        $routeExists = ($redirect && (! $routeMatched) && $this->routeExists($redirect));
118
        if (! $useRedirect || ! ($routeMatched || $routeExists)) {
119
            $redirect = false;
120
        }
121
122
        switch ($currentRoute) {
123
            case 'lmcuser/register':
124
            case 'lmcuser/login':
125
            case 'lmcuser/authenticate':
126
                if ($redirect && $routeMatched) {
127
                    return $redirect;
128
                } else {
129
                    $route = ($redirect) ?: $this->options->getLoginRedirectRoute();
130
                    return $this->router->assemble([], ['name' => $route]);
131
                }
132
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
133
            case 'lmcuser/logout':
134
                $route = ($redirect) ?: $this->options->getLogoutRedirectRoute();
135
                return $this->router->assemble([], ['name' => $route]);
136
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
137
            default:
138
                return $this->router->assemble([], ['name' => 'lmcuser']);
139
        }
140
    }
141
}
142