Passed
Push — master ( 526e5d...00c05c )
by Pouya
01:28
created

ConvertToAbsolutePath   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 200
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 88
c 1
b 0
f 0
dl 0
loc 200
rs 8.8798
wmc 44

13 Methods

Rating   Name   Duplication   Size   Complexity  
C convert() 0 53 16
A getBaseTagParsing() 0 5 2
A getStarterPath() 0 12 4
A getScheme() 0 12 4
A getPagePath() 0 3 1
A onlySitePath() 0 10 4
A getPagePathParsing() 0 5 2
A getDomain() 0 12 4
A getBaseTag() 0 3 1
A setBaseTag() 0 3 1
A setPagePath() 0 3 1
A __construct() 0 4 2
A upToLastDir() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like ConvertToAbsolutePath often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ConvertToAbsolutePath, and based on these observations, apply Extract Interface, too.

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(substr($path, 0, 1) == '#' || substr($path, 0, 1) == '?') {
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
            $rel = $path;
105
            $base = $this->uptoLastDir($this->getStarterPath());
106
            while(substr($rel, 0, 3) == '../') {
107
                $base = preg_replace('/\/([^\/]+\/)$/i', '/', $base);
108
                $rel = substr($rel, 3);
109
            }
110
            if ($base === ($this->getScheme() . '://')) {
111
                $base .= $this->getDomain();
112
            } elseif ($base===($this->getScheme(). ':/')) {
113
                $base .= '/' . $this->getDomain();
114
            }
115
            return $base . $rel;
116
        }
117
        if (empty($path)) {
118
            return $this->getPagePath();
119
        }
120
        // else
121
        return $this->uptoLastDir($this->getStarterPath()) . $path;
122
    }
123
124
    public function onlySitePath($url) {
125
//        $url = preg_replace('/(^https?:\/\/.+?\/)(.*)$/i', '$1', $url);
126
//        return rtrim($url, '/');
127
        $parseUrl = parse_url($url);
128
        if (!isset($parseUrl['scheme']) AND !isset($parseUrl['host'])) {
129
            return '';
130
        }elseif(isset($parseUrl['scheme'])){
131
            return $parseUrl['scheme'] . '://' . $parseUrl['host'];
132
        } else {
133
            return $parseUrl['host'];
134
        }
135
    }
136
137
    // Get the path with last directory
138
    // http://example.com/some/fake/path/page.html => http://example.com/some/fake/path/
139
    public function upToLastDir($url) {
140
        $parseUrl = parse_url($url);
141
        $path = '';
142
        if(isset($parseUrl['path']))
143
            $path = preg_replace('/\/([^\/]+)$/i', '', $parseUrl['path']);
144
        return rtrim($parseUrl['scheme'] . '://' . $parseUrl['host'] . $path, '/') . '/';
145
    }
146
147
148
    public function getPagePath()
149
    {
150
        return $this->pagePath;
151
    }
152
153
    /**
154
     * @param string $pagePath
155
     */
156
    public function setPagePath(string $pagePath): void
157
    {
158
        $this->pagePath = $pagePath;
159
    }
160
161
162
    public function getBaseTag()
163
    {
164
        return $this->baseTag;
165
    }
166
167
    /**
168
     * @param string $baseTag
169
     */
170
    public function setBaseTag(string $baseTag): void
171
    {
172
        $this->baseTag = $baseTag;
173
    }
174
175
    /**
176
     * @return string
177
     */
178
    private function getStarterPath(): string
179
    {
180
        if($this->starterPath===null){
181
            if($this->getBaseTag() === null) {
182
                $this->starterPath =$this->getPagePath();
183
            }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

183
            }elseif(array_key_exists('scheme', /** @scrutinizer ignore-type */ $this->getBaseTagParsing())){
Loading history...
184
                $this->starterPath = $this->getBaseTag() ;
185
            }else{
186
                $this->starterPath = $this->getPagePathParsing()['scheme'] . '://' . $this->getPagePathParsing()['host'] . $this->getBaseTag();
187
            }
188
        }
189
        return $this->starterPath;
190
    }
191
192
    private function getDomain()
193
    {
194
        if ($this->domain === null) {
195
            if($this->getBaseTag() === null) {
196
                $this->domain = $this->getPagePathParsing()['host'] . '/';
197
            }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

197
            }elseif(array_key_exists('scheme', /** @scrutinizer ignore-type */ $this->getBaseTagParsing())){
Loading history...
198
                $this->domain = $this->getBaseTagParsing()['host'] . '/';
199
            }else{
200
                $this->domain = $this->getPagePathParsing()['host'] . '/';
201
            }
202
        }
203
        return $this->domain;
204
    }
205
206
    private function getScheme()
207
    {
208
        if ($this->scheme === null) {
209
            if($this->getBaseTag() === null) {
210
                $this->scheme = $this->getPagePathParsing()['scheme'];
211
            }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

211
            }elseif(array_key_exists('scheme', /** @scrutinizer ignore-type */ $this->getBaseTagParsing())){
Loading history...
212
                $this->scheme = $this->getBaseTagParsing()['scheme'];
213
            }else{
214
                $this->scheme = $this->getPagePathParsing()['scheme'];
215
            }
216
        }
217
        return $this->scheme;
218
    }
219
220
    private function getBaseTagParsing()
221
    {
222
        if($this->baseTagParsing == null)
223
            $this->baseTagParsing = parse_url($this->getBaseTag());
224
        return $this->baseTagParsing;
225
    }
226
227
    private function getPagePathParsing()
228
    {
229
        if($this->pagePathParsing == null)
230
            $this->pagePathParsing = parse_url($this->getPagePath());
231
        return $this->pagePathParsing;
232
    }
233
}