Passed
Pull Request — master (#18)
by SignpostMarv
05:20
created

UrlUtils::resolveRelativeUrlAfterEarlyChecks()   B

Complexity

Conditions 3
Paths 1

Size

Total Lines 29
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3.0213

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 13
cts 15
cp 0.8667
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 13
nc 1
nop 2
crap 3.0213
1
<?php
2
3
namespace GoetasWebservices\XML\XSDReader\Utils;
4
5
class UrlUtils
6
{
7 56
    /**
8
     * @param string $base
9
     * @param string $rel
10 56
     *
11 56
     * @return string
12 56
     */
13
    public static function resolveRelativeUrl($base, $rel)
14 56
    {
15 2
        if (!$rel) {
16
            return $base;
17
        } elseif (
18
        /* return if already absolute URL */
19 55
            parse_url($rel, PHP_URL_SCHEME) !== null ||
20 47
            substr($rel, 0, 2) === '//'
21
        ) {
22
            return $rel;
23
        } elseif (
24 9
        /* queries and anchors */
25 2
            in_array(
26
                $rel[0],
27
                [
28
                    '#',
29 9
                    '?',
30
                ]
31
            )
32
        ) {
33
            return $base.$rel;
34
        }
35 9
36
        return static::resolveRelativeUrlAfterEarlyChecks($base, $rel);
37
    }
38 9
39
    /**
40
     * @param string $base
41 9
     * @param string $rel
42 4
     *
43 4
     * @return string
44
     */
45
    protected static function resolveRelativeUrlAfterEarlyChecks($base, $rel)
46 9
    {
47
        /* fix url file for Windows */
48 9
        $base = preg_replace('#^file:\/\/([^/])#', 'file:///\1', $base);
49 5
50 5
        /**
51
         * @var mixed[]
52 9
         *
53
         * parse base URL and convert to local variables:
54
         * $scheme, $host, $path
55
         */
56 9
        $parts = parse_url($base);
57
58
        return static::resolveRelativeUrlToAbsoluteUrl(
59 9
            $rel,
60
            (
61 9
                $rel[0] === '/'
62 9
                    ? ''  // destroy path if relative url points to root
63
                    : ( // remove non-directory element from path
64 9
                        isset($parts['path'])
65 6
                            ? preg_replace(
66 6
                                '#/[^/]*$#',
67
                                '',
68 9
                                (string) $parts['path']
69
                            )
70
                            : ''
71
                    )
72
            ),
73
            $parts
74
        );
75
    }
76
77
    /**
78
     * @param string $rel
79
     * @param string $path
80
     *
81
     * @return string
82
     */
83
    protected static function resolveRelativeUrlToAbsoluteUrl(
84
        $rel,
85
        $path,
86
        array $parts
87
    ) {
88
        /* Build absolute URL */
89
        $abs = '';
90
91
        if (isset($parts['host'])) {
92
            $abs .= (string) $parts['host'];
93
        }
94
95
        if (isset($parts['port'])) {
96
            $abs .= ':'.(string) $parts['port'];
97
        }
98
99
        $abs .= $path.'/'.$rel;
100
        $abs = static::replaceSuperfluousSlashes($abs);
101
102
        if (isset($parts['scheme'])) {
103
            $abs = (string) $parts['scheme'].'://'.$abs;
104
        }
105
106
        return $abs;
107
    }
108
109
    /**
110
     * replace superfluous slashes with a single slash.
111
     * covers:
112
     * //
113
     * /./
114
     * /foo/../.
115
     *
116
     * @param string $abs
117
     *
118
     * @return string
119
     */
120
    protected static function replaceSuperfluousSlashes($abs)
121
    {
122
        $n = 1;
123
        do {
124
            $abs = preg_replace(
125
                '#(?:(?:/\.?/)|(?!\.\.)[^/]+/\.\./)#',
126
                '/',
127
                $abs,
128
                -1,
129
                $n
130
            );
131
        } while ($n > 0);
132
133
        return $abs;
134
    }
135
}
136