Passed
Push — master ( 00c05c...4f2521 )
by Pouya
01:17
created

ConvertToAbsolutePath::isCorrectUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
4
namespace seosazi\PathConverter;
5
6
7
/**
8
 * Convert paths relative with base tag and domain to absolute path
9
 *
10
 * E.g.
11
 *      href="style.css"
12
 *      and base tag "https://www.seosazi.com/assets/"
13
 *      and web page address "https://www.seosazi.com"
14
 * becomes
15
 *     https://www.seosazi.com/assets/style.css
16
 *
17
 * Or
18
 *E.g.
19
 *      href="../../style.css"
20
 *      and base tag "https://www.seosazi.com/assets/files/"
21
 *      and web page address "https://www.seosazi.com"
22
 * becomes
23
 *     https://www.seosazi.com/style.css
24
 *
25
 *
26
 * Please report bugs on https://github.com/seosazi/path-converter/issues
27
 *
28
 * @author Pouya Pormohamad <[email protected]>
29
 * @copyright Copyright (c) 2020, Pouya Pormohamad. All rights reserved
30
 * @license MIT License
31
 */
32
class ConvertToAbsolutePath implements ConverterInterface
33
{
34
35
    /** @var string */
36
    private $pagePath;
37
    /** @var string|null */
38
    private $baseTag = null;
39
    /** @var string|null  */
40
    private $starterPath=null;
41
    /**
42
     * @var array|false|int|string|null
43
     */
44
    private $baseTagParsing;
45
    /**
46
     * @var array|false|int|string|null
47
     */
48
    private $pagePathParsing;
49
    /**
50
     * @var string
51
     */
52
    private $domain;
53
    private $scheme;
54
55
    /**
56
     * ConvertToAbsolutePath constructor.
57
     * @param $pagePath
58
     */
59
    public function __construct($pagePath=NULL)
60
    {
61
        if(isset($pagePath)) {
62
            $this->setPagePath($pagePath);
63
        }
64
    }
65
66
    /**
67
     * @inheritDoc
68
     */
69
    public function convert($path)
70
    {
71
        // Skip converting if the relative url like http://... or android-app://... etc.
72
        if (preg_match('/[a-z0-9-]{1,}(:\/\/)/i', $path)) {
73
            if(preg_match('/services:\/\//i', $path))
74
                        return '';
75
            if(preg_match('/whatsapp:\/\//i', $path))
76
                        return '';
77
            if(preg_match('/tel:/i', $path))
78
                        return '';
79
            return $path;
80
        }
81
        // Treat path as invalid if it is like javascript:... etc.
82
        if (preg_match('/^[a-zA-Z]{0,}:[^\/]{0,1}/i', $path)) {
83
            return '';
84
        }
85
        // Convert //www.google.com to http://www.google.com
86
        if(substr($path, 0, 2) == '//') {
87
            return 'http:' . $path;
88
        }
89
        // If the path is a fragment or query string,
90
        // it will be appended to the base url
91
        if($this->isHaveQueryOrFragment($path)) {
92
            return $this->getStarterPath() . $path;
93
        }
94
        // Treat paths with doc root, i.e, /about
95
        if(substr($path, 0, 1) == '/') {
96
            return $this->onlySitePath($this->getStarterPath()) . $path;
97
        }
98
        // For paths like ./foo, it will be appended to the furthest directory
99
        if(substr($path, 0, 2) == './') {
100
            return $this->uptoLastDir($this->getStarterPath()) . substr($path, 2);
101
        }
102
        // Convert paths like ../foo or ../../bar
103
        if(substr($path, 0, 3) == '../') {
104
           $removeTwoPointSlash = new RemovePathWithPointPointSlash($this, $path);
105
           return $removeTwoPointSlash->compute();
106
        }
107
        if (empty($path)) {
108
            return $this->getPagePath();
109
        }
110
        // else
111
        return $this->uptoLastDir($this->getStarterPath()) . $path;
112
    }
113
114
    public function onlySitePath($url) {
115
//        $url = preg_replace('/(^https?:\/\/.+?\/)(.*)$/i', '$1', $url);
116
//        return rtrim($url, '/');
117
        $parseUrl = parse_url($url);
118
        if ($this->isCorrectUrl($parseUrl)) {
119
            return '';
120
        }elseif(isset($parseUrl['scheme'])){
121
            return $parseUrl['scheme'] . '://' . $parseUrl['host'];
122
        } else {
123
            return $parseUrl['host'];
124
        }
125
    }
126
127
    // Get the path with last directory
128
    // http://example.com/some/fake/path/page.html => http://example.com/some/fake/path/
129
    public function upToLastDir($url) {
130
        $parseUrl = parse_url($url);
131
        $path = '';
132
        if(isset($parseUrl['path']))
133
            $path = preg_replace('/\/([^\/]+)$/i', '', $parseUrl['path']);
134
        return rtrim($parseUrl['scheme'] . '://' . $parseUrl['host'] . $path, '/') . '/';
135
    }
136
137
138
    public function getPagePath()
139
    {
140
        return $this->pagePath;
141
    }
142
143
    /**
144
     * @param string $pagePath
145
     */
146
    public function setPagePath(string $pagePath): void
147
    {
148
        $this->pagePath = $pagePath;
149
    }
150
151
152
    public function getBaseTag()
153
    {
154
        return $this->baseTag;
155
    }
156
157
    /**
158
     * @param string $baseTag
159
     */
160
    public function setBaseTag(string $baseTag): void
161
    {
162
        $this->baseTag = $baseTag;
163
    }
164
165
    /**
166
     * @return string
167
     */
168
    public function getStarterPath(): string
169
    {
170
        if($this->starterPath===null){
171
            if($this->getBaseTag() === null) {
172
                $this->starterPath =$this->getPagePath();
173
            }elseif(array_key_exists('scheme', $this->getBaseTagParsing())){
0 ignored issues
show
Bug introduced by
It seems like $this->getBaseTagParsing() can also be of type integer and string and true; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

173
            }elseif(array_key_exists('scheme', /** @scrutinizer ignore-type */ $this->getBaseTagParsing())){
Loading history...
174
                $this->starterPath = $this->getBaseTag() ;
175
            }else{
176
                $this->starterPath = $this->getPagePathParsing()['scheme'] . '://' . $this->getPagePathParsing()['host'] . $this->getBaseTag();
177
            }
178
        }
179
        return $this->starterPath;
180
    }
181
182
    public function getDomain()
183
    {
184
        if ($this->domain === null) {
185
            if($this->getBaseTag() === null) {
186
                $this->domain = $this->getPagePathParsing()['host'] . '/';
187
            }elseif(array_key_exists('scheme', $this->getBaseTagParsing())){
0 ignored issues
show
Bug introduced by
It seems like $this->getBaseTagParsing() can also be of type integer and string and true; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

187
            }elseif(array_key_exists('scheme', /** @scrutinizer ignore-type */ $this->getBaseTagParsing())){
Loading history...
188
                $this->domain = $this->getBaseTagParsing()['host'] . '/';
189
            }else{
190
                $this->domain = $this->getPagePathParsing()['host'] . '/';
191
            }
192
        }
193
        return $this->domain;
194
    }
195
196
    public function getScheme()
197
    {
198
        if ($this->scheme === null) {
199
            if($this->getBaseTag() === null) {
200
                $this->scheme = $this->getPagePathParsing()['scheme'];
201
            }elseif(array_key_exists('scheme', $this->getBaseTagParsing())){
0 ignored issues
show
Bug introduced by
It seems like $this->getBaseTagParsing() can also be of type integer and string and true; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

201
            }elseif(array_key_exists('scheme', /** @scrutinizer ignore-type */ $this->getBaseTagParsing())){
Loading history...
202
                $this->scheme = $this->getBaseTagParsing()['scheme'];
203
            }else{
204
                $this->scheme = $this->getPagePathParsing()['scheme'];
205
            }
206
        }
207
        return $this->scheme;
208
    }
209
210
    public function getBaseTagParsing()
211
    {
212
        if($this->baseTagParsing == null)
213
            $this->baseTagParsing = parse_url($this->getBaseTag());
214
        return $this->baseTagParsing;
215
    }
216
217
    public function getPagePathParsing()
218
    {
219
        if($this->pagePathParsing == null)
220
            $this->pagePathParsing = parse_url($this->getPagePath());
221
        return $this->pagePathParsing;
222
    }
223
224
    /**
225
     * @param $path
226
     * @return bool
227
     */
228
    public function isHaveQueryOrFragment($path): bool
229
    {
230
        return substr($path, 0, 1) == '#' || substr($path, 0, 1) == '?';
231
    }
232
233
    /**
234
     * @param $parseUrl
235
     * @return bool
236
     */
237
    public function isCorrectUrl($parseUrl): bool
238
    {
239
        return !isset($parseUrl['scheme']) AND !isset($parseUrl['host']);
240
    }
241
}