Completed
Pull Request — master (#125)
by
unknown
01:43
created

BasicNetworkResolver::getServerRequest()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 19
c 0
b 0
f 0
nc 8
nop 0
dl 0
loc 27
ccs 20
cts 20
cp 1
crap 8
rs 8.4444
1
<?php
2
declare(strict_types=1);
3
4
namespace Yiisoft\Yii\Web\NetworkResolver;
5
6
use Psr\Http\Message\ServerRequestInterface;
7
8
/**
9
 * Basic network resolver
10
 *
11
 * It can be used in the following cases:
12
 * - not required IP resolve to access the user's IP
13
 * - user's IP is already resolved (eg ngx_http_realip_module or similar)
14
 *
15
 * @package Yiisoft\Yii\Web\NetworkResolver
16
 */
17
class BasicNetworkResolver implements NetworkResolverInterface
18
{
19
20
    /**
21
     * @var ServerRequestInterface|null
22
     */
23
    private $baseServerRequest;
24
25
    private $protocolHeaders = [];
26
27 2
    public function getRemoteIp(): string
28
    {
29 2
        $ip = $this->getBaseServerRequest()->getServerParams()['REMOTE_ADDR'] ?? null;
30 2
        if ($ip === null) {
31
            throw new \RuntimeException('Remote IP is not available!');
32
        }
33 2
        return (string)$ip;
34
    }
35
36 2
    public function getUserIp(): string
37
    {
38 2
        return $this->getRemoteIp();
39
    }
40
41
    /**
42
     * User's connection security
43
     */
44
    public function isSecureConnection(): bool
45
    {
46
        return $this->getRequestScheme() === 'https';
0 ignored issues
show
Bug introduced by
The method getRequestScheme() does not exist on Yiisoft\Yii\Web\NetworkR...er\BasicNetworkResolver. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
        return $this->/** @scrutinizer ignore-call */ getRequestScheme() === 'https';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
47
    }
48
49 11
    public function withServerRequest(ServerRequestInterface $serverRequest)
50
    {
51 11
        $new = clone $this;
52 11
        $new->baseServerRequest = $serverRequest;
53 11
        return $new;
54
    }
55
56
    /**
57
     * @TODO: documentation
58
     * @param callable|array $protocolAndAcceptedValues
59
     * @return static
60
     */
61 7
    public function withNewProtocolHeader(string $header, $protocolAndAcceptedValues)
62
    {
63 7
        $new = clone $this;
64 7
        if (is_callable($protocolAndAcceptedValues)) {
65 1
            $new->protocolHeaders[$header] = $protocolAndAcceptedValues;
66 6
        } elseif (!is_array($protocolAndAcceptedValues)) {
67
            throw new \RuntimeException('$protocolAndAcceptedValues is not array nor callable!');
68 6
        } elseif (is_array($protocolAndAcceptedValues) && count($protocolAndAcceptedValues) === 0) {
69
            throw new \RuntimeException('$protocolAndAcceptedValues cannot be an empty array!');
70
        } else {
71 6
            $new->protocolHeaders[$header] = [];
72 6
            foreach ($protocolAndAcceptedValues as $protocol => $acceptedValues) {
73 6
                if (!is_string($protocol)) {
74
                    throw new \RuntimeException('The protocol must be type of string!');
75
                }
76 6
                $new->protocolHeaders[$header][$protocol] = array_map('strtolower', (array)$acceptedValues);
77
            }
78
        }
79 7
        return $new;
80
    }
81
82 11
    protected function getBaseServerRequest(bool $throwIfNull = true): ?ServerRequestInterface
83
    {
84 11
        if ($this->baseServerRequest === null && $throwIfNull) {
85
            throw new \RuntimeException('The server request object is not set!');
86
        }
87 11
        return $this->baseServerRequest;
88
    }
89
90 9
    public function getServerRequest(): ServerRequestInterface
91
    {
92 9
        $request = $this->getBaseServerRequest();
93 9
        $newScheme = null;
94 9
        foreach ($this->protocolHeaders as $header => $data) {
95 7
            if (!$request->hasHeader($header)) {
96 1
                continue;
97
            }
98 6
            $headerValues = $request->getHeader($header);
99 6
            if (is_callable($data)) {
100 1
                $newScheme = call_user_func($data, $headerValues, $header, $request);
101 1
                break;
102
            }
103 5
            $headerValue = strtolower($headerValues[0]);
104 5
            foreach ($data as $protocol => $acceptedValues) {
105 5
                if (!in_array($headerValue, $acceptedValues)) {
106 1
                    continue;
107
                }
108 4
                $newScheme = $protocol;
109 4
                break 2;
110
            }
111
        }
112 9
        $uri = $request->getUri();
113 9
        if ($newScheme !== null && $newScheme !== $uri->getScheme()) {
114 5
            $request = $request->withUri($uri->withScheme($newScheme));
115
        }
116 9
        return $request;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $request could return the type null which is incompatible with the type-hinted return Psr\Http\Message\ServerRequestInterface. Consider adding an additional type-check to rule them out.
Loading history...
117
    }
118
}
119