Completed
Push — master ( 893872...3f3cc0 )
by Joschi
02:50
created

AuraRouterAdapter   B

Complexity

Total Complexity 9

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 16

Test Coverage

Coverage 88.89%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 108
wmc 9
lcom 1
cbo 16
ccs 40
cts 45
cp 0.8889
rs 8.4614

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 2
A registerRoute() 0 20 2
A dispatchRequestToRoute() 0 13 2
B getRouteAction() 0 24 3
1
<?php
2
3
/**
4
 * apparat-server
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Server
8
 * @subpackage  Apparat\Server\Infrastructure
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Server\Infrastructure\Route;
38
39
use Apparat\Kernel\Ports\Kernel;
40
use Apparat\Server\Domain\Contract\ActionRouteInterface;
41
use Apparat\Server\Domain\Contract\RouteInterface;
42
use Apparat\Server\Domain\Contract\RouterContainerInterface;
43
use Apparat\Server\Ports\Action\ActionInterface;
44
use Aura\Router\RouterContainer;
45
use Aura\Router\Rule;
46
use Psr\Http\Message\ResponseInterface;
47
use Psr\Http\Message\ServerRequestInterface;
48
49
/**
50
 * Aura.Router adapter
51
 *
52
 * @package Apparat\Server
53
 * @subpackage Apparat\Server\Infrastructure
54
 */
55
class AuraRouterAdapter implements RouterContainerInterface
56
{
57
    /**
58
     * Aura.Router container
59
     *
60
     * @var RouterContainer
61
     */
62
    protected $routerContainer;
63
64
    /**
65
     * Constructor
66
     *
67
     * @param RouterContainer $routerContainer Router container
68
     */
69 2
    public function __construct(RouterContainer $routerContainer)
70
    {
71 2
        $this->routerContainer = $routerContainer;
72
73
        /** @var Rule\RuleIterator $ruleIterator */
74 2
        $ruleIterator = $routerContainer->getRuleIterator();
75 2
        $ruleIterator->set([
76 2
            new Rule\Secure(),
77 2
            new Rule\Host(),
78 2
            new ObjectPath(parse_url(getenv('APPARAT_BASE_URL'), PHP_URL_PATH) ?: null),
79 2
            new Rule\Allows(),
80 2
            new Rule\Accepts(),
81 2
        ]);
82 2
    }
83
84
    /**
85
     * Register a route
86
     *
87
     * @param RouteInterface $route Route
88
     * @return RouterContainerInterface Self reference
89
     */
90 2
    public function registerRoute(RouteInterface $route)
91
    {
92
        /** @var AuraRoute $auraRoute */
93 2
        $auraRoute = Kernel::create($route->isObject() ? AuraObjectRoute::class : AuraRoute::class);
94 2
        $auraRoute->name($route->getName())
95 2
            ->path($route->getPath())
96 2
            ->allows($route->getVerbs())
97 2
            ->handler($route->getAction())
98 2
            ->tokens($route->getTokens())
99 2
            ->defaults($route->getDefaults())
100 2
            ->wildcard($route->getWildcard())
101 2
            ->host($route->getHost())
102 2
            ->accepts($route->getAccepts())
103 2
            ->auth($route->getAuth())
104 2
            ->secure($route->getSecure())
0 ignored issues
show
Bug introduced by
It seems like $route->getSecure() targeting Apparat\Server\Domain\Co...eInterface::getSecure() can also be of type null; however, Aura\Router\Route::secure() 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...
105 2
            ->extras($route->getExtras());
106 2
        $this->routerContainer->getMap()->addRoute($auraRoute);
107
108 2
        return $this;
109
    }
110
111
    /**
112
     * Dispatch a request to a route
113
     *
114
     * @param ServerRequestInterface $request
115
     * @return ActionRouteInterface $route
116
     */
117 70
    public function dispatchRequestToRoute(ServerRequestInterface $request)
118
    {
119 70
        $matcher = $this->routerContainer->getMatcher();
120 70
        $route = $matcher->match($request);
121
122
        // If a matching route was found
123 70
        if ($route instanceof ActionRouteInterface) {
124 70
            return $route;
125
        }
126
127
        // Else create an error route
128
        return AuraErrorRoute::cast($matcher->getFailedRoute());
129
    }
130
131
    /**
132
     * Prepare and return a route action
133
     *
134
     * @param ServerRequestInterface $request Request
135
     * @param ActionRouteInterface $route Route
136
     * @return ActionInterface|Callable $action Action
137
     */
138 70
    public function getRouteAction(ServerRequestInterface $request, ActionRouteInterface $route)
139
    {
140
        // Preprocess the matched attributes
141 70
        $route->preprocessAttributes();
142
143
        // Copy all route attributes to the server request
144 70
        foreach ($route->attributes as $key => $val) {
0 ignored issues
show
Bug introduced by
Accessing attributes on the interface Apparat\Server\Domain\Co...ct\ActionRouteInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
145 70
            $request = $request->withAttribute($key, $val);
146 70
        }
147
148
        /** @var AbstractActionRoute $route */
149 70
        $handler = $route->getHandler();
150
151
        // If the handler is a callable
152 70
        if (is_callable($handler)) {
153
            return function () use ($handler, $request) {
154
                /** @var ResponseInterface $response */
155
                $response = $handler($request);
156
                return $response;
157
            };
158
        }
159
160 70
        return Kernel::create($handler, [$request]);
0 ignored issues
show
Bug introduced by
It seems like $handler defined by $route->getHandler() on line 149 can also be of type object<Apparat\Server\Do...ntract\ActionInterface>; however, Apparat\Kernel\Ports\Kernel::create() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
161
    }
162
}
163