Completed
Push — master ( 706ec6...902e66 )
by Jan-Petter
04:48
created

AllowClient::isHostListed()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
c 1
b 1
f 1
dl 0
loc 22
rs 8.9197
cc 4
eloc 16
nc 6
nop 2
1
<?php
2
namespace vipnytt\RobotsTxtParser\Client\Directives;
3
4
use vipnytt\RobotsTxtParser\Exceptions\ClientException;
5
use vipnytt\RobotsTxtParser\Parser\UriParser;
6
use vipnytt\RobotsTxtParser\RobotsTxtInterface;
7
8
/**
9
 * Class AllowClient
10
 *
11
 * @see https://github.com/VIPnytt/RobotsTxtParser/blob/master/docs/methods/AllowClient.md for documentation
12
 * @package vipnytt\RobotsTxtParser\Client\Directives
13
 */
14
class AllowClient implements ClientInterface, RobotsTxtInterface
15
{
16
    use DirectiveClientCommons;
17
18
    /**
19
     * Paths
20
     * @var array
21
     */
22
    private $paths;
23
24
    /**
25
     * Host
26
     * @var HostClient
27
     */
28
    private $host;
29
30
    /**
31
     * Clean-param
32
     * @var CleanParamClient
33
     */
34
    private $cleanParam;
35
36
    /**
37
     * AllowClient constructor.
38
     *
39
     * @param array $paths
40
     * @param HostClient $host
41
     * @param CleanParamClient $cleanParam
42
     */
43
    public function __construct(array $paths, HostClient $host, CleanParamClient $cleanParam)
44
    {
45
        $this->host = $host;
46
        $this->paths = $paths;
47
        $this->cleanParam = $cleanParam;
48
    }
49
50
    /**
51
     * Check
52
     *
53
     * @param  string $uri
54
     * @return bool
55
     */
56
    public function isListed($uri)
57
    {
58
        $path = $this->getPath($uri);
59
        return (
60
            $this->checkPaths($path, $this->paths) ||
61
            $this->isHostListed($uri, $this->host->export()) ||
0 ignored issues
show
Bug introduced by
It seems like $this->host->export() targeting vipnytt\RobotsTxtParser\...es\HostClient::export() can also be of type null or string; however, vipnytt\RobotsTxtParser\...wClient::isHostListed() does only seem to accept array<integer,string>, 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...
62
            !empty($this->cleanParam->detect($path))
63
        );
64
    }
65
66
    /**
67
     * Get path and query
68
     *
69
     * @param string $uri
70
     * @return string
71
     * @throws ClientException
72
     */
73
    private function getPath($uri)
74
    {
75
        $uriParser = new UriParser($uri);
76
        // Encode
77
        $uri = explode('#', $uriParser->encode(), 2)[0];
78
        if (mb_strpos($uri, '/') === 0) {
79
            // URI is already an path
80
            return $uri;
81
        }
82
        if (!$uriParser->validate()) {
83
            throw new ClientException('Invalid URI');
84
        }
85
        $path = (($path = parse_url($uri, PHP_URL_PATH)) === null) ? '/' : $path;
86
        $query = (($query = parse_url($uri, PHP_URL_QUERY)) === null) ? '' : '?' . $query;
87
        return $path . $query;
88
    }
89
90
    /**
91
     * Is host listed by directive
92
     *
93
     * @param string $uri
94
     * @param string[] $hosts
95
     * @return bool
96
     */
97
    private function isHostListed($uri, $hosts)
98
    {
99
        $uriParser = new UriParser($uri);
100
        $uri = $uriParser->encode();
101
        $parts = [
102
            'scheme' => parse_url($uri, PHP_URL_SCHEME),
103
            'host' => parse_url($uri, PHP_URL_HOST),
104
        ];
105
        $parts['port'] = is_int($port = parse_url($uri, PHP_URL_PORT)) ? $port : getservbyname($parts['scheme'], 'tcp');
106
        $cases = [
107
            $parts['host'],
108
            $parts['host'] . ':' . $parts['port'],
109
            $parts['scheme'] . '://' . $parts['host'],
110
            $parts['scheme'] . '://' . $parts['host'] . ':' . $parts['port']
111
        ];
112
        foreach ($hosts as $host) {
113
            if (in_array($host, $cases)) {
114
                return true;
115
            }
116
        }
117
        return false;
118
    }
119
120
    /**
121
     * Export
122
     *
123
     * @return array
124
     */
125
    public function export()
126
    {
127
        return [
128
            'host' => $this->host->export(),
129
            'path' => $this->paths,
130
            'clean-param' => $this->cleanParam->export(),
131
        ];
132
    }
133
}
134