Completed
Push — master ( 70c415...6060ab )
by Paweł
02:58
created

Url::checkDomain()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Wszetko Sitemap.
7
 *
8
 * (c) Paweł Kłopotek-Główczewski <[email protected]>
9
 *
10
 * This source file is subject to the MIT license that is bundled
11
 * with this source code in the file LICENSE.
12
 */
13
14
namespace Wszetko\Sitemap\Helpers;
15
16
/**
17
 * Class Url.
18
 *
19
 * @package Wszetko\Sitemap\Helpers
20
 */
21
class Url
22
{
23
    /**
24
     * @param string $url
25
     *
26
     * @return bool|string
27
     *
28
     * @see https://bugs.php.net/bug.php?id=52923
29
     * @see https://www.php.net/manual/en/function.parse-url.php#114817
30
     */
31 138
    public static function normalizeUrl(string $url)
32
    {
33 138
        $encodedUrl = preg_replace_callback(
34 138
            '%[^:/@?&=#]+%usD',
35
            function ($matches) {
36 138
                return rawurlencode($matches[0]);
37 138
            },
38 69
            $url
39
        );
40
41 138
        if (null === $encodedUrl) {
42
            // @codeCoverageIgnoreStart
43
            return false;
44
            // @codeCoverageIgnoreEnd
45
        }
46
47 138
        $url = parse_url($encodedUrl);
48
49 138
        if (empty($url) || !isset($url['host'])) {
50 6
            return false;
51
        }
52
53 136
        $url = array_map('urldecode', $url);
54 136
        $url['host'] = idn_to_ascii($url['host'], IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
55
56 136
        if (empty($url['scheme']) || !is_string($url['host']) || !self::checkDomain($url['host'])) {
57 2
            return false;
58
        }
59
60 134
        if (!empty($url['path'])) {
61 16
            $url['path'] = explode('/', $url['path']);
62 16
            $parts = [];
63
64 16
            foreach ($url['path'] as $element) {
65 16
                switch ($element) {
66 16
                    case '.':
67 2
                        break;
68 16
                    case '..':
69 2
                        array_pop($parts);
70
71 2
                        break;
72
                    default:
73 16
                        $parts[] = rawurlencode($element);
74
75 16
                        break;
76
                }
77
            }
78
79 16
            $url['path'] = implode('/', $parts);
80
        }
81
82 134
        if (isset($url['query']) && is_string($url['query']) && '' !== $url['query']) {
83 2
            parse_str($url['query'], $query);
84
            array_walk($query, function (&$val, &$var) {
85 2
                $var = rawurlencode($var);
86 2
                $val = rawurlencode($val);
87 2
            });
88 2
            $url['query'] = http_build_query($query);
89
        }
90
91 134
        $user = '';
92
93 134
        if (isset($url['user']) && is_string($url['user']) && '' !== $url['user']) {
94 4
            $user = $url['user'];
95
96 4
            if (isset($url['pass']) && is_string($url['pass']) && '' !== $url['pass']) {
97 4
                $user .= ':' . $url['pass'];
98
            }
99
100 4
            $user .= '@';
101
        }
102
103
        return
104 134
            $url['scheme'] . '://'
105 134
            . $user
106 134
            . mb_strtolower($url['host'])
107 134
            . ((isset($url['port']) && is_string($url['port']) && '' !== $url['port']) ? ':' . $url['port'] : '')
108 134
            . ((isset($url['path'])) ? $url['path'] : '')
109 134
            . (isset($url['query']) && (is_string($url['query']) && '' !== $url['query']) ? '?' . $url['query'] : '')
110 134
            . (isset($url['fragment']) && (is_string($url['fragment']) && '' !== $url['fragment']) ? '#' . $url['fragment'] : '');
111
    }
112
113
    /**
114
     * @param string $domain
115
     *
116
     * @return bool
117
     */
118 140
    public static function checkDomain(string $domain): bool
119
    {
120 140
        if ('.' == mb_substr($domain, -1) || '.' == mb_substr($domain, 0, 1)) {
121 4
            return false;
122
        }
123
124 140
        $domain = idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
125
126 140
        return (bool) filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
127
    }
128
}
129