Overview

Namespaces

  • Contrib
    • Bundle
      • CoverallsBundle
        • Console
        • Entity
      • CoverallsV1Bundle
        • Api
        • Collector
        • Command
        • Config
        • Entity
          • Git
    • Component
      • File
      • Log
      • System
        • Git
  • Guzzle
    • Batch
      • Exception
    • Cache
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
      • QueryAggregator
    • Inflection
    • Iterator
    • Log
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Async
      • Backoff
      • Cache
      • Cookie
        • CookieJar
        • Exception
      • CurlAuth
      • ErrorResponse
        • Exception
      • History
      • Log
      • Md5
      • Mock
      • Oauth
    • Service
      • Builder
      • Command
        • Factory
        • LocationVisitor
          • Request
          • Response
      • Description
      • Exception
      • Resource
    • Stream
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Config
        • Definition
          • Builder
          • Exception
        • Exception
        • Loader
        • Resource
        • Util
      • Console
        • Command
        • Formatter
        • Helper
        • Input
        • Output
        • Tester
      • EventDispatcher
        • Debug
      • Finder
        • Adapter
        • Comparator
        • Exception
        • Expression
        • Iterator
        • Shell
      • Stopwatch
      • Yaml
        • Exception

Classes

  • AbstractEntityBodyDecorator
  • CachingEntityBody
  • Client
  • EntityBody
  • IoEmittingEntityBody
  • Mimetypes
  • QueryString
  • ReadLimitEntityBody
  • RedirectPlugin
  • Url

Interfaces

  • ClientInterface
  • EntityBodyInterface
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  1: <?php
  2: 
  3: namespace Guzzle\Http;
  4: 
  5: use Guzzle\Common\Exception\InvalidArgumentException;
  6: use Guzzle\Parser\ParserRegistry;
  7: 
  8: /**
  9:  * Parses and generates URLs based on URL parts. In favor of performance, URL parts are not validated.
 10:  */
 11: class Url
 12: {
 13:     protected $scheme;
 14:     protected $host;
 15:     protected $port;
 16:     protected $username;
 17:     protected $password;
 18:     protected $path = '';
 19:     protected $fragment;
 20: 
 21:     /**
 22:      * @var QueryString Query part of the URL
 23:      */
 24:     protected $query;
 25: 
 26:     /**
 27:      * Factory method to create a new URL from a URL string
 28:      *
 29:      * @param string $url Full URL used to create a Url object
 30:      *
 31:      * @return Url
 32:      */
 33:     public static function factory($url)
 34:     {
 35:         $parts = ParserRegistry::getInstance()->getParser('url')->parseUrl($url);
 36: 
 37:         // Convert the query string into a QueryString object
 38:         if (0 !== strlen($parts['query'])) {
 39:             $parts['query'] = QueryString::fromString($parts['query']);
 40:         }
 41: 
 42:         return new self($parts['scheme'], $parts['host'], $parts['user'],
 43:             $parts['pass'], $parts['port'], $parts['path'], $parts['query'],
 44:             $parts['fragment']);
 45:     }
 46: 
 47:     /**
 48:      * Build a URL from parse_url parts. The generated URL will be a relative URL if a scheme or host are not provided.
 49:      *
 50:      * @param array $parts Array of parse_url parts
 51:      *
 52:      * @return string
 53:      */
 54:     public static function buildUrl(array $parts)
 55:     {
 56:         $url = $scheme = '';
 57: 
 58:         if (isset($parts['scheme'])) {
 59:             $scheme = $parts['scheme'];
 60:             $url .= $scheme . ':';
 61:         }
 62: 
 63:         if (isset($parts['host'])) {
 64:             $url .= '//';
 65:             if (isset($parts['user'])) {
 66:                 $url .= $parts['user'];
 67:                 if (isset($parts['pass'])) {
 68:                     $url .= ':' . $parts['pass'];
 69:                 }
 70:                 $url .=  '@';
 71:             }
 72: 
 73:             $url .= $parts['host'];
 74: 
 75:             // Only include the port if it is not the default port of the scheme
 76:             if (isset($parts['port'])
 77:                 && !(($scheme == 'http' && $parts['port'] == 80) || ($scheme == 'https' && $parts['port'] == 443))
 78:             ) {
 79:                 $url .= ':' . $parts['port'];
 80:             }
 81:         }
 82: 
 83:         // Add the path component if present
 84:         if (isset($parts['path']) && 0 !== strlen($parts['path'])) {
 85:             // Always ensure that the path begins with '/' if set and something is before the path
 86:             if ($url && $parts['path'][0] != '/' && substr($url, -1)  != '/') {
 87:                 $url .= '/';
 88:             }
 89:             $url .= $parts['path'];
 90:         }
 91: 
 92:         // Add the query string if present
 93:         if (isset($parts['query'])) {
 94:             $url .= '?' . $parts['query'];
 95:         }
 96: 
 97:         // Ensure that # is only added to the url if fragment contains anything.
 98:         if (isset($parts['fragment'])) {
 99:             $url .= '#' . $parts['fragment'];
100:         }
101: 
102:         return $url;
103:     }
104: 
105:     /**
106:      * Create a new URL from URL parts
107:      *
108:      * @param string                   $scheme   Scheme of the URL
109:      * @param string                   $host     Host of the URL
110:      * @param string                   $username Username of the URL
111:      * @param string                   $password Password of the URL
112:      * @param int                      $port     Port of the URL
113:      * @param string                   $path     Path of the URL
114:      * @param QueryString|array|string $query    Query string of the URL
115:      * @param string                   $fragment Fragment of the URL
116:      */
117:     public function __construct($scheme, $host, $username = null, $password = null, $port = null, $path = null, QueryString $query = null, $fragment = null)
118:     {
119:         $this->scheme = $scheme;
120:         $this->host = $host;
121:         $this->port = $port;
122:         $this->username = $username;
123:         $this->password = $password;
124:         $this->fragment = $fragment;
125:         if (!$query) {
126:             $this->query = new QueryString();
127:         } else {
128:             $this->setQuery($query);
129:         }
130:         $this->setPath($path);
131:     }
132: 
133:     /**
134:      * Clone the URL
135:      */
136:     public function __clone()
137:     {
138:         $this->query = clone $this->query;
139:     }
140: 
141:     /**
142:      * Returns the URL as a URL string
143:      *
144:      * @return string
145:      */
146:     public function __toString()
147:     {
148:         return self::buildUrl($this->getParts());
149:     }
150: 
151:     /**
152:      * Get the parts of the URL as an array
153:      *
154:      * @return array
155:      */
156:     public function getParts()
157:     {
158:         return array(
159:             'scheme' => $this->scheme,
160:             'user' => $this->username,
161:             'pass' => $this->password,
162:             'host' => $this->host,
163:             'port' => $this->port,
164:             'path' => $this->getPath(),
165:             'query' => (string) $this->query ?: null,
166:             'fragment' => $this->fragment,
167:         );
168:     }
169: 
170:     /**
171:      * Set the host of the request.
172:      *
173:      * @param string $host Host to set (e.g. www.yahoo.com, yahoo.com)
174:      *
175:      * @return Url
176:      */
177:     public function setHost($host)
178:     {
179:         if (strpos($host, ':') === false) {
180:             $this->host = $host;
181:         } else {
182:             list($host, $port) = explode(':', $host);
183:             $this->host = $host;
184:             $this->setPort($port);
185:         }
186: 
187:         return $this;
188:     }
189: 
190:     /**
191:      * Get the host part of the URL
192:      *
193:      * @return string
194:      */
195:     public function getHost()
196:     {
197:         return $this->host;
198:     }
199: 
200:     /**
201:      * Set the scheme part of the URL (http, https, ftp, etc)
202:      *
203:      * @param string $scheme Scheme to set
204:      *
205:      * @return Url
206:      */
207:     public function setScheme($scheme)
208:     {
209:         $this->scheme = $scheme;
210: 
211:         return $this;
212:     }
213: 
214:     /**
215:      * Get the scheme part of the URL
216:      *
217:      * @return string
218:      */
219:     public function getScheme()
220:     {
221:         return $this->scheme;
222:     }
223: 
224:     /**
225:      * Set the port part of the URL
226:      *
227:      * @param int $port Port to set
228:      *
229:      * @return Url
230:      */
231:     public function setPort($port)
232:     {
233:         $this->port = $port;
234: 
235:         return $this;
236:     }
237: 
238:     /**
239:      * Get the port part of the URl. Will return the default port for a given scheme if no port has been set.
240:      *
241:      * @return int|null
242:      */
243:     public function getPort()
244:     {
245:         if ($this->port) {
246:             return $this->port;
247:         } elseif ($this->scheme == 'http') {
248:             return 80;
249:         } elseif ($this->scheme == 'https') {
250:             return 443;
251:         }
252: 
253:         return null;
254:     }
255: 
256:     /**
257:      * Set the path part of the URL
258:      *
259:      * @param array|string $path Path string or array of path segments
260:      *
261:      * @return Url
262:      */
263:     public function setPath($path)
264:     {
265:         if (is_array($path)) {
266:             $this->path = '/' . implode('/', $path);
267:         } else {
268:             $this->path = (string) $path;
269:         }
270: 
271:         return $this;
272:     }
273: 
274:     /**
275:      * Normalize the URL so that double slashes and relative paths are removed
276:      *
277:      * @return Url
278:      */
279:     public function normalizePath()
280:     {
281:         if (!$this->path || $this->path == '/' || $this->path == '*') {
282:             return $this;
283:         }
284: 
285:         // Replace // and /./ with /
286:         $this->path = str_replace(array('/./', '//'), '/', $this->path);
287: 
288:         // Remove dot segments
289:         if (strpos($this->path, '..') !== false) {
290: 
291:             // Remove trailing relative paths if possible
292:             $segments = $this->getPathSegments();
293:             $last = end($segments);
294:             $trailingSlash = false;
295:             if ($last === '') {
296:                 array_pop($segments);
297:                 $trailingSlash = true;
298:             }
299: 
300:             while ($last == '..' || $last == '.') {
301:                 if ($last == '..') {
302:                     array_pop($segments);
303:                     $last = array_pop($segments);
304:                 }
305:                 if ($last == '.' || $last == '') {
306:                     $last = array_pop($segments);
307:                 }
308:             }
309: 
310:             $this->path = implode('/', $segments);
311:             if ($trailingSlash) {
312:                 $this->path .= '/';
313:             }
314:         }
315: 
316:         return $this;
317:     }
318: 
319:     /**
320:      * Add a relative path to the currently set path
321:      *
322:      * @param string $relativePath Relative path to add
323:      *
324:      * @return Url
325:      */
326:     public function addPath($relativePath)
327:     {
328:         if (!$relativePath || $relativePath == '/') {
329:             return $this;
330:         }
331: 
332:         // Add a leading slash if needed
333:         if ($relativePath[0] != '/') {
334:             $relativePath = '/' . $relativePath;
335:         }
336: 
337:         return $this->setPath(str_replace('//', '/', $this->getPath() . $relativePath));
338:     }
339: 
340:     /**
341:      * Get the path part of the URL
342:      *
343:      * @return string
344:      */
345:     public function getPath()
346:     {
347:         return $this->path;
348:     }
349: 
350:     /**
351:      * Get the path segments of the URL as an array
352:      *
353:      * @return array
354:      */
355:     public function getPathSegments()
356:     {
357:         return array_slice(explode('/', $this->getPath()), 1);
358:     }
359: 
360:     /**
361:      * Set the password part of the URL
362:      *
363:      * @param string $password Password to set
364:      *
365:      * @return Url
366:      */
367:     public function setPassword($password)
368:     {
369:         $this->password = $password;
370: 
371:         return $this;
372:     }
373: 
374:     /**
375:      * Get the password part of the URL
376:      *
377:      * @return null|string
378:      */
379:     public function getPassword()
380:     {
381:         return $this->password;
382:     }
383: 
384:     /**
385:      * Set the username part of the URL
386:      *
387:      * @param string $username Username to set
388:      *
389:      * @return Url
390:      */
391:     public function setUsername($username)
392:     {
393:         $this->username = $username;
394: 
395:         return $this;
396:     }
397: 
398:     /**
399:      * Get the username part of the URl
400:      *
401:      * @return null|string
402:      */
403:     public function getUsername()
404:     {
405:         return $this->username;
406:     }
407: 
408:     /**
409:      * Get the query part of the URL as a QueryString object
410:      *
411:      * @return QueryString
412:      */
413:     public function getQuery()
414:     {
415:         return $this->query;
416:     }
417: 
418:     /**
419:      * Set the query part of the URL
420:      *
421:      * @param QueryString|string|array $query Query to set
422:      *
423:      * @return Url
424:      */
425:     public function setQuery($query)
426:     {
427:         if (is_string($query)) {
428:             $output = null;
429:             parse_str($query, $output);
430:             $this->query = new QueryString($output);
431:         } elseif (is_array($query)) {
432:             $this->query = new QueryString($query);
433:         } elseif ($query instanceof QueryString) {
434:             $this->query = $query;
435:         }
436: 
437:         return $this;
438:     }
439: 
440:     /**
441:      * Get the fragment part of the URL
442:      *
443:      * @return null|string
444:      */
445:     public function getFragment()
446:     {
447:         return $this->fragment;
448:     }
449: 
450:     /**
451:      * Set the fragment part of the URL
452:      *
453:      * @param string $fragment Fragment to set
454:      *
455:      * @return Url
456:      */
457:     public function setFragment($fragment)
458:     {
459:         $this->fragment = $fragment;
460: 
461:         return $this;
462:     }
463: 
464:     /**
465:      * Check if this is an absolute URL
466:      *
467:      * @return bool
468:      */
469:     public function isAbsolute()
470:     {
471:         return $this->scheme && $this->host;
472:     }
473: 
474:     /**
475:      * Combine the URL with another URL. Follows the rules specific in RFC 3986 section 5.4.
476:      *
477:      * @param string $url Relative URL to combine with
478:      *
479:      * @return Url
480:      * @throws InvalidArgumentException
481:      * @link http://tools.ietf.org/html/rfc3986#section-5.4
482:      */
483:     public function combine($url)
484:     {
485:         $url = self::factory($url);
486: 
487:         // Use the more absolute URL as the base URL
488:         if (!$this->isAbsolute() && $url->isAbsolute()) {
489:             $url = $url->combine($this);
490:         }
491: 
492:         // Passing a URL with a scheme overrides everything
493:         if ($buffer = $url->getScheme()) {
494:             $this->scheme = $buffer;
495:             $this->host = $url->getHost();
496:             $this->port = $url->getPort();
497:             $this->username = $url->getUsername();
498:             $this->password = $url->getPassword();
499:             $this->path = $url->getPath();
500:             $this->query = $url->getQuery();
501:             $this->fragment = $url->getFragment();
502:             return $this;
503:         }
504: 
505:         // Setting a host overrides the entire rest of the URL
506:         if ($buffer = $url->getHost()) {
507:             $this->host = $buffer;
508:             $this->port = $url->getPort();
509:             $this->username = $url->getUsername();
510:             $this->password = $url->getPassword();
511:             $this->path = $url->getPath();
512:             $this->fragment = $url->getFragment();
513:             return $this;
514:         }
515: 
516:         $path = $url->getPath();
517:         $query = $url->getQuery();
518: 
519:         if (!$path) {
520:             if (count($query)) {
521:                 $this->query = $query;
522:             }
523:         } else {
524:             if ($path[0] == '/') {
525:                 $this->path = $path;
526:             } else {
527:                 $this->path .= '/' . $path;
528:             }
529:             $this->normalizePath();
530:             $this->query = $query;
531:         }
532: 
533:         $this->fragment = $url->getFragment();
534: 
535:         return $this;
536:     }
537: }
538: 
php-coveralls API documentation generated by ApiGen 2.8.0