| Total Complexity | 51 |
| Total Lines | 273 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like UriDetector 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 UriDetector, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 30 | class UriDetector |
||
| 31 | { |
||
| 32 | /** |
||
| 33 | * The URL components |
||
| 34 | * |
||
| 35 | * @var array |
||
| 36 | */ |
||
| 37 | protected $aUrl; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @param array $aServerParams The server environment variables |
||
| 41 | * |
||
| 42 | * @return void |
||
| 43 | */ |
||
| 44 | private function setScheme(array $aServerParams): void |
||
| 45 | { |
||
| 46 | if(isset($this->aUrl['scheme'])) |
||
| 47 | { |
||
| 48 | return; |
||
| 49 | } |
||
| 50 | if(isset($aServerParams['HTTP_SCHEME'])) |
||
| 51 | { |
||
| 52 | $this->aUrl['scheme'] = $aServerParams['HTTP_SCHEME']; |
||
| 53 | return; |
||
| 54 | } |
||
| 55 | if((isset($aServerParams['HTTPS']) && strtolower($aServerParams['HTTPS']) === 'on') || |
||
| 56 | (isset($aServerParams['HTTP_X_FORWARDED_SSL']) && $aServerParams['HTTP_X_FORWARDED_SSL'] === 'on') || |
||
| 57 | (isset($aServerParams['HTTP_X_FORWARDED_PROTO']) && $aServerParams['HTTP_X_FORWARDED_PROTO'] === 'https')) |
||
| 58 | { |
||
| 59 | $this->aUrl['scheme'] = 'https'; |
||
| 60 | return; |
||
| 61 | } |
||
| 62 | $this->aUrl['scheme'] = 'http'; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Get the URL from the $aServerParams var |
||
| 67 | * |
||
| 68 | * @param array $aServerParams The server environment variables |
||
| 69 | * @param string $sKey The key in the $aServerParams array |
||
| 70 | * |
||
| 71 | * @return void |
||
| 72 | */ |
||
| 73 | private function setHostFromServer(array $aServerParams, string $sKey): void |
||
| 74 | { |
||
| 75 | if(isset($this->aUrl['host']) || empty($aServerParams[$sKey])) |
||
| 76 | { |
||
| 77 | return; |
||
| 78 | } |
||
| 79 | if(strpos($aServerParams[$sKey], ':') === false) |
||
| 80 | { |
||
| 81 | $this->aUrl['host'] = $aServerParams[$sKey]; |
||
| 82 | return; |
||
| 83 | } |
||
| 84 | list($this->aUrl['host'], $this->aUrl['port']) = explode(':', $aServerParams[$sKey]); |
||
| 85 | } |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @param array $aServerParams The server environment variables |
||
| 89 | * |
||
| 90 | * @return void |
||
| 91 | * @throws UriException |
||
| 92 | */ |
||
| 93 | private function setHost(array $aServerParams): void |
||
| 105 | } |
||
| 106 | } |
||
| 107 | |||
| 108 | /** |
||
| 109 | * @param array $aServerParams The server environment variables |
||
| 110 | * |
||
| 111 | * @return void |
||
| 112 | */ |
||
| 113 | private function setPath(array $aServerParams): void |
||
| 114 | { |
||
| 115 | if(isset($this->aUrl['path']) && strlen(basename($this->aUrl['path'])) === 0) |
||
| 116 | { |
||
| 117 | unset($this->aUrl['path']); |
||
| 118 | } |
||
| 119 | if(isset($this->aUrl['path'])) |
||
| 120 | { |
||
| 121 | return; |
||
| 122 | } |
||
| 123 | $aPath = parse_url($aServerParams['PATH_INFO'] ?? ($aServerParams['PHP_SELF'] ?? '')); |
||
| 124 | if(isset($aPath['path'])) |
||
| 125 | { |
||
| 126 | $this->aUrl['path'] = $aPath['path']; |
||
| 127 | } |
||
| 128 | } |
||
| 129 | |||
| 130 | /** |
||
| 131 | * @return string |
||
| 132 | */ |
||
| 133 | private function getPath(): string |
||
| 134 | { |
||
| 135 | return '/' . ltrim($this->aUrl['path'], '/'); |
||
| 136 | } |
||
| 137 | |||
| 138 | /** |
||
| 139 | * @return string |
||
| 140 | */ |
||
| 141 | private function getUser(): string |
||
| 153 | } |
||
| 154 | |||
| 155 | /** |
||
| 156 | * @return string |
||
| 157 | */ |
||
| 158 | private function getPort(): string |
||
| 159 | { |
||
| 160 | if(isset($this->aUrl['port']) && |
||
| 161 | (($this->aUrl['scheme'] === 'http' && $this->aUrl['port'] != 80) || |
||
| 162 | ($this->aUrl['scheme'] === 'https' && $this->aUrl['port'] != 443))) |
||
| 163 | { |
||
| 164 | return ':' . $this->aUrl['port']; |
||
| 165 | } |
||
| 166 | return ''; |
||
| 167 | } |
||
| 168 | |||
| 169 | /** |
||
| 170 | * @param array $aServerParams The server environment variables |
||
| 171 | * |
||
| 172 | * @return void |
||
| 173 | */ |
||
| 174 | private function setQuery(array $aServerParams): void |
||
| 179 | } |
||
| 180 | } |
||
| 181 | |||
| 182 | /** |
||
| 183 | * @return string |
||
| 184 | */ |
||
| 185 | private function getQuery(): string |
||
| 204 | } |
||
| 205 | |||
| 206 | /** |
||
| 207 | * Detect the URI of the current request |
||
| 208 | * |
||
| 209 | * @param array $aServerParams The server environment variables |
||
| 210 | * |
||
| 211 | * @return string |
||
| 212 | * @throws UriException |
||
| 213 | */ |
||
| 214 | public function detect(array $aServerParams): string |
||
| 215 | { |
||
| 216 | $this->aUrl = []; |
||
| 217 | // Try to get the request URL |
||
| 218 | if(isset($aServerParams['REQUEST_URI'])) |
||
| 219 | { |
||
| 220 | $this->aUrl = parse_url($aServerParams['REQUEST_URI']); |
||
| 221 | } |
||
| 222 | |||
| 223 | // Fill in the empty values |
||
| 224 | $this->setScheme($aServerParams); |
||
| 225 | $this->setHost($aServerParams); |
||
| 226 | $this->setPath($aServerParams); |
||
| 227 | $this->setQuery($aServerParams); |
||
| 228 | |||
| 229 | // Build the URL: Start with scheme, user and pass |
||
| 230 | return $this->aUrl['scheme'] . '://' . $this->getUser() . $this->aUrl['host'] . |
||
| 231 | $this->getPort() . str_replace(['"', "'", '<', '>'], |
||
| 232 | ['%22', '%27', '%3C', '%3E'], $this->getPath() . $this->getQuery()); |
||
| 233 | } |
||
| 234 | |||
| 235 | /** |
||
| 236 | * @param string $sQueryPart |
||
| 237 | * @param string $sKey |
||
| 238 | * @param string $sValue |
||
| 239 | * |
||
| 240 | * @return string |
||
| 241 | */ |
||
| 242 | private function makeQueryPart(string $sQueryPart, string $sKey, string $sValue): string |
||
| 243 | { |
||
| 244 | return $sValue === '' && strpos($sQueryPart, "$sKey=") === false ? |
||
| 245 | rawurlencode($sKey) : rawurlencode($sKey) . '=' . rawurlencode($sValue); |
||
| 246 | } |
||
| 247 | |||
| 248 | /** |
||
| 249 | * @param string $sQueryPart |
||
| 250 | * @param array $aServerParams |
||
| 251 | * |
||
| 252 | * @return string |
||
| 253 | */ |
||
| 254 | private function parseQueryPart(string $sQueryPart, array $aServerParams): string |
||
| 255 | { |
||
| 256 | $aQueryParts = []; |
||
| 257 | parse_str($sQueryPart, $aQueryParts); |
||
| 258 | if(empty($aQueryParts)) |
||
| 259 | { |
||
| 260 | // Couldn't break up the query, but there's one there. |
||
| 261 | // Possibly "http://url/page.html?query1234" type of query? |
||
| 262 | // Try to get data from the server environment var. |
||
| 263 | parse_str($aServerParams['QUERY_STRING'] ?? '', $aQueryParts); |
||
| 264 | } |
||
| 265 | if(($aQueryParts)) |
||
| 266 | { |
||
| 267 | $aNewQueryParts = []; |
||
| 268 | foreach($aQueryParts as $sKey => $sValue) |
||
| 269 | { |
||
| 270 | $aNewQueryParts[] = $this->makeQueryPart($sQueryPart, $sKey, $sValue); |
||
| 271 | } |
||
| 272 | return '?' . implode('&', $aNewQueryParts); |
||
| 273 | } |
||
| 274 | return trim($sQueryPart); |
||
| 275 | } |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Make the specified URL suitable for redirect |
||
| 279 | * |
||
| 280 | * @param string $sURL The relative or fully qualified URL |
||
| 281 | * @param array $aServerParams The server environment variables |
||
| 282 | * |
||
| 283 | * @return string |
||
| 284 | */ |
||
| 285 | public function redirect(string $sURL, array $aServerParams): string |
||
| 303 | } |
||
| 304 | } |
||
| 305 |