ParsedUri.php

File

drupal/core/vendor/easyrdf/easyrdf/lib/EasyRdf/ParsedUri.php
View source
<?php

/**
 * EasyRdf
 *
 * LICENSE
 *
 * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
 *    promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    EasyRdf
 * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
 * @license    http://www.opensource.org/licenses/bsd-license.php
 * @version    $Id$
 */

/**
 * A RFC3986 compliant URI parser
 *
 * @package    EasyRdf
 * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
 * @license    http://www.opensource.org/licenses/bsd-license.php
 * @link       http://www.ietf.org/rfc/rfc3986.txt
 */
class EasyRdf_ParsedUri {

  // For all URIs:
  private $scheme = null;
  private $fragment = null;

  // For hierarchical URIs:
  private $authority = null;
  private $path = null;
  private $query = null;
  const URI_REGEX = "|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?|";

  /** Constructor for creating a new parsed URI
   *
   * The $uri parameter can either be a string or an
   * associative array with the following keys:
   * scheme, authority, path, query, fragment
   *
   * @param  mixed $uri  The URI as a string or an array
   * @return object EasyRdf_ParsedUri
   */
  public function __construct($uri = null) {
    if (is_string($uri)) {
      if (preg_match(self::URI_REGEX, $uri, $matches)) {
        if (!empty($matches[1])) {
          $this->scheme = isset($matches[2]) ? $matches[2] : '';
        }
        if (!empty($matches[3])) {
          $this->authority = isset($matches[4]) ? $matches[4] : '';
        }
        $this->path = isset($matches[5]) ? $matches[5] : '';
        if (!empty($matches[6])) {
          $this->query = isset($matches[7]) ? $matches[7] : '';
        }
        if (!empty($matches[8])) {
          $this->fragment = isset($matches[9]) ? $matches[9] : '';
        }
      }
    }
    elseif (is_array($uri)) {
      $this->scheme = isset($uri['scheme']) ? $uri['scheme'] : null;
      $this->authority = isset($uri['authority']) ? $uri['authority'] : null;
      $this->path = isset($uri['path']) ? $uri['path'] : null;
      $this->query = isset($uri['query']) ? $uri['query'] : null;
      $this->fragment = isset($uri['fragment']) ? $uri['fragment'] : null;
    }
  }

  /** Returns true if this is an absolute (complete) URI
   * @return boolean
   */
  public function isAbsolute() {
    return $this->scheme !== null;
  }

  /** Returns true if this is an relative (partial) URI
   * @return boolean
   */
  public function isRelative() {
    return $this->scheme === null;
  }

  /** Returns the scheme of the URI (e.g. http)
   * @return string
   */
  public function getScheme() {
    return $this->scheme;
  }

  /** Sets the scheme of the URI (e.g. http)
   * @param string $scheme The new value for the scheme of the URI
   */
  public function setScheme($scheme) {
    $this->scheme = $scheme;
  }

  /** Returns the authority of the URI (e.g. www.example.com:8080)
   * @return string
   */
  public function getAuthority() {
    return $this->authority;
  }

  /** Sets the authority of the URI (e.g. www.example.com:8080)
   * @param string $authority The new value for the authority component of the URI
   */
  public function setAuthority($authority) {
    $this->authority = $authority;
  }

  /** Returns the path of the URI (e.g. /foo/bar)
   * @return string
   */
  public function getPath() {
    return $this->path;
  }

  /** Set the path of the URI (e.g. /foo/bar)
   * @param string $path The new value for the path component of the URI
   */
  public function setPath($path) {
    $this->path = $path;
  }

  /** Returns the query string part of the URI (e.g. foo=bar)
   * @return string
   */
  public function getQuery() {
    return $this->query;
  }

  /** Set the query string of the URI (e.g. foo=bar)
   * @param string $query The new value for the query string component of the URI
   */
  public function setQuery($query) {
    $this->query = $query;
  }

  /** Returns the fragment part of the URI (i.e. after the #)
   * @return string
   */
  public function getFragment() {
    return $this->fragment;
  }

  /** Set the fragment of the URI (i.e. after the #)
   * @param string $fragment The new value for the fragment component of the URI
   */
  public function setFragment($fragment) {
    $this->fragment = $fragment;
  }

  /**
   * Normalises the path of this URI if it has one. Normalising a path means
   * that any unnecessary '.' and '..' segments are removed. For example, the
   * URI http://example.com/a/b/../c/./d would be normalised to
   * http://example.com/a/c/d
   *
   * @return object EasyRdf_ParsedUri
   */
  public function normalise() {
    if (empty($this->path)) {
      return $this;
    }

    // Remove ./ from the start
    if (substr($this->path, 0, 2) == './') {

      // Remove both characters
      $this->path = substr($this->path, 2);
    }

    // Remove /. from the end
    if (substr($this->path, -2) == '/.') {

      // Remove only the last dot, not the slash!
      $this->path = substr($this->path, 0, -1);
    }
    if (substr($this->path, -3) == '/..') {
      $this->path .= '/';
    }

    // Split the path into its segments
    $segments = explode('/', $this->path);
    $newSegments = array();

    // Remove all unnecessary '.' and '..' segments
    foreach ($segments as $segment) {
      if ($segment == '..') {

        // Remove the previous part of the path
        $count = count($newSegments);
        if ($count > 0 && $newSegments[$count - 1]) {
          array_pop($newSegments);
        }
      }
      elseif ($segment == '.') {

        // Ignore
        continue;
      }
      else {
        array_push($newSegments, $segment);
      }
    }

    // Construct the new normalised path
    $this->path = implode($newSegments, '/');

    // Allow easy chaining of methods
    return $this;
  }

  /**
   * Resolves a relative URI using this URI as the base URI.
   */
  public function resolve($relUri) {

    // If it is a string, then convert it to a parsed object
    if (is_string($relUri)) {
      $relUri = new EasyRdf_ParsedUri($relUri);
    }

    // This code is based on the pseudocode in section 5.2.2 of RFC3986
    $target = new EasyRdf_ParsedUri();
    if ($relUri->scheme) {
      $target->scheme = $relUri->scheme;
      $target->authority = $relUri->authority;
      $target->path = $relUri->path;
      $target->query = $relUri->query;
    }
    else {
      if ($relUri->authority) {
        $target->authority = $relUri->authority;
        $target->path = $relUri->path;
        $target->query = $relUri->query;
      }
      else {
        if (empty($relUri->path)) {
          $target->path = $this->path;
          if ($relUri->query) {
            $target->query = $relUri->query;
          }
          else {
            $target->query = $this->query;
          }
        }
        else {
          if (substr($relUri->path, 0, 1) == '/') {
            $target->path = $relUri->path;
          }
          else {
            $path = $this->path;
            $lastSlash = strrpos($path, '/');
            if ($lastSlash !== false) {
              $path = substr($path, 0, $lastSlash + 1);
            }
            else {
              $path = '/';
            }
            $target->path .= $path . $relUri->path;
          }
          $target->query = $relUri->query;
        }
        $target->authority = $this->authority;
      }
      $target->scheme = $this->scheme;
    }
    $target->fragment = $relUri->fragment;
    $target
      ->normalise();
    return $target;
  }

  /** Convert the parsed URI back into a string
   *
   * @return string The URI as a string
   */
  public function toString() {
    $str = '';
    if ($this->scheme !== null) {
      $str .= $this->scheme . ':';
    }
    if ($this->authority !== null) {
      $str .= '//' . $this->authority;
    }
    $str .= $this->path;
    if ($this->query !== null) {
      $str .= '?' . $this->query;
    }
    if ($this->fragment !== null) {
      $str .= '#' . $this->fragment;
    }
    return $str;
  }

  /** Magic method to convert the URI, when casted, back to a string
   *
   * @return string The URI as a string
   */
  public function __toString() {
    return $this
      ->toString();
  }

}

Classes

Namesort descending Description
EasyRdf_ParsedUri A RFC3986 compliant URI parser