Completed
Push — master ( 90174b...a197f9 )
by Changwan
03:50
created

Dispatcher::getPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Router;
3
4
use Closure;
5
use FastRoute\Dispatcher as FastDispatcher;
6
use Psr\Http\Message\ServerRequestInterface;
7
use Wandu\Router\Contracts\LoaderInterface;
8
use Wandu\Router\Contracts\ResponsifierInterface;
9
10
class Dispatcher
11
{
12
    /** @var \Wandu\Router\Contracts\LoaderInterface */
13
    protected $loader;
14
15
    /** @var \Wandu\Router\Responsifier\NullResponsifier */
16
    protected $responsifier;
17
    
18
    /** @var \Wandu\Router\Configuration */
19
    protected $config;
20
    
21
    /** @var \Closure */
22
    protected $handler;
23
    
24
    /** @var \Wandu\Router\CompiledRoutes */
25
    protected $compiledRoutes;
26
    
27 24
    public function __construct(
28
        LoaderInterface $loader = null,
29
        ResponsifierInterface $responsifier = null,
30
        Configuration $config = null
31
    ) {
32 24
        $this->loader = $loader;
33 24
        $this->responsifier = $responsifier;
0 ignored issues
show
Documentation Bug introduced by
It seems like $responsifier can also be of type object<Wandu\Router\Cont...\ResponsifierInterface>. However, the property $responsifier is declared as type object<Wandu\Router\Resp...ifier\NullResponsifier>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
34 24
        $this->config = $config ?: new Configuration([]);
35 24
    }
36
37 1
    public function flush()
38
    {
39 1
        if ($this->config->isCacheEnabled()) {
40 1
            @unlink($this->config->getCacheFile());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
41
        }
42 1
    }
43
44
    /**
45
     * @deprecated use setRoutes
46
     * 
47
     * @param \Closure $handler
48
     * @return \Wandu\Router\Dispatcher
49
     */
50
    public function withRoutes(Closure $handler)
51
    {
52
        $inst = clone $this;
53
        $inst->setRoutes($handler);
54
        return $inst;
55
    }
56
57
    /**
58
     * @param \Closure $handler
59
     */
60 24
    public function setRoutes(Closure $handler)
61
    {
62 24
        $this->compiledRoutes = null;
63 24
        $this->handler = $handler;
64 24
    }
65
    
66
    /**
67
     * @param \Psr\Http\Message\ServerRequestInterface $request
68
     * @return \Psr\Http\Message\ResponseInterface
69
     */
70 24
    public function dispatch(ServerRequestInterface $request)
71
    {
72 24
        $compiledRoutes = $this->getCompiledRoutes();
73 24
        $request = $this->applyVirtualMethod($request);
74 24
        return $compiledRoutes->dispatch($request, $this->loader, $this->responsifier);
75
    }
76
    
77 24
    protected function getCompiledRoutes(): CompiledRoutes
78
    {
79 24
        if (!$this->compiledRoutes) {
80 24
            $cacheEnabled = $this->config->isCacheEnabled();
81 24
            if ($this->isCached()) {
82 2
                $this->compiledRoutes = $this->restoreCache();
83
            } else {
84 24
                $this->compiledRoutes = CompiledRoutes::compile($this->handler, $this->config);
85 24
                if ($cacheEnabled) {
86 2
                    $this->storeCache($this->compiledRoutes);
87
                }
88
            }
89
        }
90 24
        return $this->compiledRoutes;
91
    }
92
93
    /**
94
     * @param \Psr\Http\Message\ServerRequestInterface $request
95
     * @return \Psr\Http\Message\ServerRequestInterface
96
     */
97 24
    protected function applyVirtualMethod(ServerRequestInterface $request)
98
    {
99 24
        if (!$this->config->isVirtualMethodEnabled()) {
100 21
            return $request;
101
        }
102 3
        $parsedBody = $request->getParsedBody();
103 3
        if (isset($parsedBody['_method'])) {
104 1
            return $request->withMethod(strtoupper($parsedBody['_method']));
105
        }
106 2
        if ($request->hasHeader('X-Http-Method-Override')) {
107 1
            return $request->withMethod(strtoupper($request->getHeaderLine('X-Http-Method-Override')));
108
        }
109 1
        return $request;
110
    }
111
112
    /**
113
     * @return bool
114
     */
115 24
    public function isCached(): bool
116
    {
117 24
        $cacheEnabled = $this->config->isCacheEnabled();
118 24
        $cacheFile = $this->config->getCacheFile();
119 24
        return $cacheEnabled && file_exists($cacheFile);
120
    }
121
    
122 2
    private function storeCache(CompiledRoutes $routes)
123
    {
124 2
        file_put_contents($this->config->getCacheFile(), serialize($routes));
125 2
    }
126
127 2
    private function restoreCache(): CompiledRoutes
128
    {
129 2
        return unserialize(file_get_contents($this->config->getCacheFile()));
130
    }
131
}
132