Completed
Push — master ( 53bdfc...124206 )
by Jonathan
03:41 queued 01:50
created

Url::fromCurrent()   F

Complexity

Conditions 14
Paths 270

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
c 3
b 1
f 1
dl 0
loc 40
rs 3.7522
cc 14
eloc 23
nc 270
nop 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Purl package, a project by Jonathan H. Wage.
5
 *
6
 * (c) 2013 Jonathan H. Wage
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Purl;
13
14
use Pdp\PublicSuffixListManager;
15
use Pdp\Parser as PslParser;
16
17
/**
18
 * Url is a simple OO class for manipulating Urls in PHP.
19
 *
20
 * @author      Jonathan H. Wage <[email protected]>
21
 *
22
 * @property string $scheme
23
 * @property string $host
24
 * @property integer $port
25
 * @property string $user
26
 * @property string $pass
27
 * @property \Purl\Path $path
28
 * @property \Purl\Query $query
29
 * @property \Purl\Fragment $fragment
30
 * @property string $publicSuffix
31
 * @property string $registerableDomain
32
 * @property string $subdomain
33
 * @property string $canonical
34
 * @property string $resource
35
 */
36
class Url extends AbstractPart
37
{
38
    /**
39
     * @var string The original url string.
40
     */
41
    private $url;
42
43
    /**
44
     * @var ParserInterface
45
     */
46
    private $parser;
47
48
    /**
49
     * @var array
50
     */
51
    protected $data = array(
52
        'scheme'             => null,
53
        'host'               => null,
54
        'port'               => null,
55
        'user'               => null,
56
        'pass'               => null,
57
        'path'               => null,
58
        'query'              => null,
59
        'fragment'           => null,
60
        'publicSuffix'       => null,
61
        'registerableDomain' => null,
62
        'subdomain'          => null,
63
        'canonical'          => null,
64
        'resource'           => null
65
    );
66
67
    /**
68
     * @var array
69
     */
70
    protected $partClassMap = array(
71
        'path' => 'Purl\Path',
72
        'query' => 'Purl\Query',
73
        'fragment' => 'Purl\Fragment'
74
    );
75
76
    /**
77
     * Construct a new Url instance.
78
     *
79
     * @param string $url
80
     * @param ParserInterface $parser
81
     */
82
    public function __construct($url = null, ParserInterface $parser = null)
83
    {
84
        $this->url = $url;
85
        $this->parser = $parser;
86
    }
87
88
    /**
89
     * Static convenience method for creating a new Url instance.
90
     *
91
     * @param string $url
92
     * @return Url
93
     */
94
    public static function parse($url)
95
    {
96
        return new self($url);
97
    }
98
99
    /**
100
     * Extracts urls from a string of text.
101
     *
102
     * @param string $string
103
     * @return array $urls
104
     */
105
    public static function extract($string)
106
    {
107
        $regex = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
108
109
        preg_match_all($regex, $string, $matches);
110
        $urls = array();
111
        foreach ($matches[0] as $url) {
112
            $urls[] = self::parse($url);
113
        }
114
115
        return $urls;
116
    }
117
118
    /**
119
     * Creates an Url instance based on data available on $_SERVER variable.
120
     *
121
     * @return Url
122
     */
123
    public static function fromCurrent()
124
    {
125
        $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http';
126
127
        $host = $_SERVER['HTTP_HOST'];
128
        $baseUrl = "$scheme://$host";
129
130
        $url = new self($baseUrl);
131
132
        if (!empty($_SERVER['REQUEST_URI'])) {
133
            if (strpos($_SERVER['REQUEST_URI'], '?') !== false) {
134
                list($path, $query) = explode('?', $_SERVER['REQUEST_URI'], 2);
135
            } else {
136
                $path = $_SERVER['REQUEST_URI'];
137
                $query = '';
138
            }
139
140
            $url->set('path', $path);
141
            $url->set('query', $query);
142
        }
143
144
        // Only set port if different from default (80 or 443)
145
        if (!empty($_SERVER['SERVER_PORT'])) {
146
            $port = $_SERVER['SERVER_PORT'];
147
            if (($scheme == 'http' && $port != 80) ||
148
                ($scheme == 'https' && $port != 443)) {
149
                $url->set('port', $port);
150
            }
151
        }
152
153
        // Authentication
154
        if (!empty($_SERVER['PHP_AUTH_USER'])) {
155
            $url->set('user', $_SERVER['PHP_AUTH_USER']);
156
            if (!empty($_SERVER['PHP_AUTH_PW'])) {
157
                $url->set('pass', $_SERVER['PHP_AUTH_PW']);
158
            }
159
        }
160
161
        return $url;
162
    }
163
164
    /**
165
     * Gets the ParserInterface instance used to parse this Url instance.
166
     *
167
     * @return ParserInterface
168
     */
169
    public function getParser()
170
    {
171
        if ($this->parser === null) {
172
            $this->parser = self::createDefaultParser();
173
        }
174
175
        return $this->parser;
176
    }
177
178
    /**
179
     * Sets the ParserInterface instance to use to parse this Url instance.
180
     *
181
     * @param ParserInterface $parser
182
     */
183
    public function setParser(ParserInterface $parser)
184
    {
185
        $this->parser = $parser;
186
    }
187
188
    /**
189
     * Join this Url instance together with another Url instance or a string url.
190
     *
191
     * @param Url|string $url
192
     * @return Url
193
     */
194
    public function join($url)
195
    {
196
        $this->initialize();
197
        $parts = $this->getParser()->parseUrl($url);
198
199
        foreach ($parts as $key => $value) {
200
            if ($value !== null) {
201
                $this->data[$key] = $value;
202
            }
203
        }
204
205
        foreach ($this->data as $key => $value) {
206
            $this->data[$key] = $this->preparePartValue($key, $value);
207
        }
208
209
        return $this;
210
    }
211
212
    /**
213
     * @inheritDoc
214
     * @override
215
     */
216
    public function set($key, $value)
217
    {
218
        $this->initialize();
219
        $this->data[$key] = $this->preparePartValue($key, $value);
220
221
        return $this;
222
    }
223
224
    /**
225
     * Set the Path instance.
226
     *
227
     * @param Path
228
     */
229
    public function setPath(Path $path)
230
    {
231
        $this->data['path'] = $path;
232
233
        return $this;
234
    }
235
236
    /**
237
     * Get the Path instance.
238
     *
239
     * @return Path
240
     */
241
    public function getPath()
242
    {
243
        $this->initialize();
244
        return $this->data['path'];
245
    }
246
247
    /**
248
     * Set the Query instance.
249
     *
250
     * @param Query
251
     */
252
    public function setQuery(Query $query)
253
    {
254
        $this->data['query'] = $query;
255
256
        return $this;
257
    }
258
259
    /**
260
     * Get the Query instance.
261
     *
262
     * @return Query
263
     */
264
    public function getQuery()
265
    {
266
        $this->initialize();
267
        return $this->data['query'];
268
    }
269
270
    /**
271
     * Set the Fragment instance.
272
     *
273
     * @param Fragment
274
     */
275
    public function setFragment(Fragment $fragment)
276
    {
277
        $this->data['fragment'] = $fragment;
278
279
        return $this;
280
    }
281
282
    /**
283
     * Get the Fragment instance.
284
     *
285
     * @return Fragment
286
     */
287
    public function getFragment()
288
    {
289
        $this->initialize();
290
        return $this->data['fragment'];
291
    }
292
293
    /**
294
     * Gets the netloc part of the Url. It is the user, pass, host and port returned as a string.
295
     *
296
     * @return string
297
     */
298
    public function getNetloc()
299
    {
300
        $this->initialize();
301
        return ($this->user && $this->pass ? $this->user.($this->pass ? ':'.$this->pass : '').'@' : '').$this->host.($this->port ? ':'.$this->port : '');
302
    }
303
304
    /**
305
     * Builds a string url from this Url instance internal data and returns it.
306
     *
307
     * @return string
308
     */
309
    public function getUrl()
310
    {
311
        $this->initialize();
312
        return self::httpBuildUrl(array_map(function($value) {
313
            return (string) $value;
314
        }, $this->data));
315
    }
316
317
    /**
318
     * Set the string url for this Url instance and sets initialized to false.
319
     *
320
     * @param string
321
     */
322
    public function setUrl($url)
323
    {
324
        $this->initialized = false;
325
        $this->data = array();
326
        $this->url = $url;
327
    }
328
329
    /**
330
     * Checks if the Url instance is absolute or not.
331
     *
332
     * @return boolean
333
     */
334
    public function isAbsolute()
335
    {
336
        $this->initialize();
337
        return $this->scheme && $this->host;
338
    }
339
340
    /**
341
     * @inheritDoc
342
     */
343
    public function __toString()
344
    {
345
        return $this->getUrl();
346
    }
347
348
    /**
349
     * @inheritDoc
350
     */
351
    protected function doInitialize()
352
    {
353
        $parts = $this->getParser()->parseUrl($this->url);
354
355
        foreach ($parts as $k => $v) {
356
            if (!isset($this->data[$k])) {
357
                $this->data[$k] = $v;
358
            }
359
        }
360
361
        foreach ($this->data as $key => $value) {
362
            $this->data[$key] = $this->preparePartValue($key, $value);
363
        }
364
    }
365
366
    /**
367
     * Reconstructs a string URL from an array of parts.
368
     *
369
     * @param array $parts
370
     * @return string $url
371
     */
372
    private static function httpBuildUrl(array $parts)
373
    {
374
        $parts['path'] = ltrim($parts['path'], '/');
375
376
        return sprintf('%s://%s%s%s/%s%s%s',
377
            $parts['scheme'],
378
            $parts['user'] ? sprintf('%s%s@', $parts['user'], $parts['pass'] ? sprintf(':%s', $parts['pass']) : '') : '',
379
            $parts['host'],
380
            $parts['port'] ? sprintf(':%d', $parts['port']) : '',
381
            $parts['path'] ? $parts['path'] : '',
382
            $parts['query'] ? '?'.$parts['query'] : '',
383
            $parts['fragment'] ? '#'.$parts['fragment'] : ''
384
        );
385
    }
386
387
    /**
388
     * Creates the default Parser instance to parse urls.
389
     *
390
     * @return Parser
391
     */
392
    private static function createDefaultParser()
393
    {
394
        $pslManager = new PublicSuffixListManager(dirname(dirname(__DIR__)) . '/data');
395
        $pslParser = new PslParser($pslManager->getList());
396
        
397
        return new Parser($pslParser);
398
    }
399
}
400