You are here

class Mimeparse in Services 6.3

Same name and namespace in other branches
  1. 7.3 servers/rest_server/lib/mimeparse.php \Mimeparse

Hierarchy

Expanded class hierarchy of Mimeparse

File

servers/rest_server/lib/mimeparse.php, line 2

View source
class Mimeparse {

  /**
   * Carves up a mime-type and returns an Array of the [type, subtype, params]
   * where "params" is a Hash of all the parameters for the media range.
   *
   * For example, the media range "application/xhtml;q=0.5" would
   * get parsed into:
   *
   * array("application", "xhtml", array( "q" => "0.5" ))
   *
   * @param string $mime_type
   * @return array ($type, $subtype, $params)
   */
  public function parse_mime_type($mime_type) {
    $parts = explode(";", $mime_type);
    $params = array();
    foreach ($parts as $i => $param) {
      if (strpos($param, '=') !== false) {
        list($k, $v) = explode('=', trim($param));
        $params[$k] = $v;
      }
    }
    $full_type = trim($parts[0]);

    /* Java URLConnection class sends an Accept header that includes a single "*"
       Turn it into a legal wildcard. */
    if ($full_type == '*') {
      $full_type = '*/*';
    }
    list($type, $subtype) = explode('/', $full_type);
    if (!$subtype) {
      throw new Exception("malformed mime type");
    }
    return array(
      trim($type),
      trim($subtype),
      $params,
    );
  }

  /**
   * Carves up a media range and returns an Array of the
   * [type, subtype, params] where "params" is a Hash of all
   * the parameters for the media range.
   *
   * For example, the media range "application/*;q=0.5" would
   * get parsed into:
   *
   * array("application", "*", ( "q", "0.5" ))
   *
   * In addition this function also guarantees that there
   * is a value for "q" in the params dictionary, filling it
   * in with a proper default if necessary.
   *
   * @param string $range
   * @return array ($type, $subtype, $params)
   */
  public function parse_media_range($range) {
    list($type, $subtype, $params) = $this
      ->parse_mime_type($range);
    if (!(isset($params['q']) && $params['q'] && floatval($params['q']) && floatval($params['q']) <= 1 && floatval($params['q']) >= 0)) {
      $params['q'] = '1';
    }
    return array(
      $type,
      $subtype,
      $params,
    );
  }

  /**
   * Find the best match for a given mime-type against a list of
   * media_ranges that have already been parsed by Mimeparser::parse_media_range()
   *
   * Returns the fitness and the "q" quality parameter of the best match, or an
   * array [-1, 0] if no match was found. Just as for Mimeparser::quality(),
   * "parsed_ranges" must be an Enumerable of parsed media ranges.
   *
   * @param string $mime_type
   * @param array  $parsed_ranges
   * @return array ($best_fitness, $best_fit_q)
   */
  public function fitness_and_quality_parsed($mime_type, $parsed_ranges) {
    $best_fitness = -1;
    $best_fit_q = 0;
    list($target_type, $target_subtype, $target_params) = $this
      ->parse_media_range($mime_type);
    foreach ($parsed_ranges as $item) {
      list($type, $subtype, $params) = $item;
      if (($type == $target_type or $type == "*" or $target_type == "*") && ($subtype == $target_subtype or $subtype == "*" or $target_subtype == "*")) {
        $param_matches = 0;
        foreach ($target_params as $k => $v) {
          if ($k != 'q' && isset($params[$k]) && $v == $params[$k]) {
            $param_matches++;
          }
        }
        $fitness = $type == $target_type ? 100 : 0;
        $fitness += $subtype == $target_subtype ? 10 : 0;
        $fitness += $param_matches;
        if ($fitness > $best_fitness) {
          $best_fitness = $fitness;
          $best_fit_q = $params['q'];
        }
      }
    }
    return array(
      $best_fitness,
      (double) $best_fit_q,
    );
  }

  /**
   * Find the best match for a given mime-type against a list of
   * media_ranges that have already been parsed by Mimeparser::parse_media_range()
   *
   * Returns the "q" quality parameter of the best match, 0 if no match
   * was found. This function behaves the same as Mimeparser::quality() except that
   * "parsed_ranges" must be an Enumerable of parsed media ranges.
   *
   * @param string $mime_type
   * @param array  $parsed_ranges
   * @return float $q
   */
  public function quality_parsed($mime_type, $parsed_ranges) {
    list($fitness, $q) = $this
      ->fitness_and_quality_parsed($mime_type, $parsed_ranges);
    return $q;
  }

  /**
   * Returns the quality "q" of a mime-type when compared against
   * the media-ranges in ranges. For example:
   *
   * Mimeparser::quality("text/html", "text/*;q=0.3, text/html;q=0.7,
   * text/html;level=1, text/html;level=2;q=0.4, *\/*;q=0.5")
   * => 0.7
   *
   * @param unknown_type $mime_type
   * @param unknown_type $ranges
   * @return unknown
   */
  public function quality($mime_type, $ranges) {
    $parsed_ranges = explode(',', $ranges);
    foreach ($parsed_ranges as $i => $r) {
      $parsed_ranges[$i] = $this
        ->parse_media_range($r);
    }
    return $this
      ->quality_parsed($mime_type, $parsed_ranges);
  }

  /**
   * Takes a list of supported mime-types and finds the best match
   * for all the media-ranges listed in header. The value of header
   * must be a string that conforms to the format of the HTTP Accept:
   * header. The value of supported is an Enumerable of mime-types
   *
   * Mimeparser::best_match(array("application/xbel+xml", "text/xml"), "text/*;q=0.5,*\/*; q=0.1")
   * => "text/xml"
   *
   * @param  array  $supported
   * @param  string $header
   * @return mixed  $mime_type or NULL
   */
  public function best_match($supported, $header) {
    $parsed_header = explode(',', $header);
    foreach ($parsed_header as $i => $r) {
      $parsed_header[$i] = $this
        ->parse_media_range($r);
    }
    $weighted_matches = array();
    foreach ($supported as $mime_type) {
      $weighted_matches[] = array(
        $this
          ->fitness_and_quality_parsed($mime_type, $parsed_header),
        $mime_type,
      );
    }
    array_multisort($weighted_matches);
    $a = $weighted_matches[count($weighted_matches) - 1];
    return empty($a[0][1]) ? null : $a[1];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Mimeparse::best_match public function Takes a list of supported mime-types and finds the best match for all the media-ranges listed in header. The value of header must be a string that conforms to the format of the HTTP Accept: header. The value of supported is an Enumerable of mime-types
Mimeparse::fitness_and_quality_parsed public function Find the best match for a given mime-type against a list of media_ranges that have already been parsed by Mimeparser::parse_media_range()
Mimeparse::parse_media_range public function Carves up a media range and returns an Array of the [type, subtype, params] where "params" is a Hash of all the parameters for the media range.
Mimeparse::parse_mime_type public function Carves up a mime-type and returns an Array of the [type, subtype, params] where "params" is a Hash of all the parameters for the media range.
Mimeparse::quality public function Returns the quality "q" of a mime-type when compared against the media-ranges in ranges. For example:
Mimeparse::quality_parsed public function Find the best match for a given mime-type against a list of media_ranges that have already been parsed by Mimeparser::parse_media_range()