You are here

Result.php in Zircon Profile 8.0

File

vendor/easyrdf/easyrdf/lib/EasyRdf/Sparql/Result.php
View source
<?php

/**
 * EasyRdf
 *
 * LICENSE
 *
 * Copyright (c) 2009-2013 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-2013 Nicholas J Humfrey
 * @license    http://www.opensource.org/licenses/bsd-license.php
 */

/**
 * Class for returned for SPARQL SELECT and ASK query responses.
 *
 * @package    EasyRdf
 * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
 * @license    http://www.opensource.org/licenses/bsd-license.php
 */
class EasyRdf_Sparql_Result extends ArrayIterator {
  private $type = null;
  private $boolean = null;
  private $ordered = null;
  private $distinct = null;
  private $fields = array();

  /** A constant for the SPARQL Query Results XML Format namespace */
  const SPARQL_XML_RESULTS_NS = 'http://www.w3.org/2005/sparql-results#';

  /** Create a new SPARQL Result object
   *
   * You should not normally need to create a SPARQL result
   * object directly - it will be constructed automatically
   * for you by EasyRdf_Sparql_Client.
   *
   * @param string $data      The SPARQL result body
   * @param string $mimeType  The MIME type of the result
   */
  public function __construct($data, $mimeType) {
    if ($mimeType == 'application/sparql-results+xml') {
      return $this
        ->parseXml($data);
    }
    elseif ($mimeType == 'application/sparql-results+json') {
      return $this
        ->parseJson($data);
    }
    else {
      throw new EasyRdf_Exception("Unsupported SPARQL Query Results format: {$mimeType}");
    }
  }

  /** Get the query result type (boolean/bindings)
   *
   * ASK queries return a result of type 'boolean'.
   * SELECT query return a result of type 'bindings'.
   *
   * @return string The query result type.
   */
  public function getType() {
    return $this->type;
  }

  /** Return the boolean value of the query result
   *
   * If the query was of type boolean then this method will
   * return either true or false. If the query was of some other
   * type then this method will return null.
   *
   * @return boolean The result of the query.
   */
  public function getBoolean() {
    return $this->boolean;
  }

  /** Return true if the result of the query was true.
   *
   * @return boolean True if the query result was true.
   */
  public function isTrue() {
    return $this->boolean == true;
  }

  /** Return false if the result of the query was false.
   *
   * @return boolean True if the query result was false.
   */
  public function isFalse() {
    return $this->boolean == false;
  }

  /** Return the number of fields in a query result of type bindings.
   *
   * @return integer The number of fields.
   */
  public function numFields() {
    return count($this->fields);
  }

  /** Return the number of rows in a query result of type bindings.
   *
   * @return integer The number of rows.
   */
  public function numRows() {
    return count($this);
  }

  /** Get the field names in a query result of type bindings.
   *
   * @return array The names of the fields in the result.
   */
  public function getFields() {
    return $this->fields;
  }

  /** Return a human readable view of the query result.
   *
   * This method is intended to be a debugging aid and will
   * return a pretty-print view of the query result.
   *
   * @param  string  $format  Either 'text' or 'html'
   */
  public function dump($format = 'html') {
    if ($this->type == 'bindings') {
      $result = '';
      if ($format == 'html') {
        $result .= "<table class='sparql-results' style='border-collapse:collapse'>";
        $result .= "<tr>";
        foreach ($this->fields as $field) {
          $result .= "<th style='border:solid 1px #000;padding:4px;" . "vertical-align:top;background-color:#eee;'>" . "?{$field}</th>";
        }
        $result .= "</tr>";
        foreach ($this as $row) {
          $result .= "<tr>";
          foreach ($this->fields as $field) {
            if (isset($row->{$field})) {
              $result .= "<td style='border:solid 1px #000;padding:4px;" . "vertical-align:top'>" . $row->{$field}
                ->dumpValue($format) . "</td>";
            }
            else {
              $result .= "<td>&nbsp;</td>";
            }
          }
          $result .= "</tr>";
        }
        $result .= "</table>";
      }
      else {

        // First calculate the width of each comment
        $colWidths = array();
        foreach ($this->fields as $field) {
          $colWidths[$field] = strlen($field);
        }
        $textData = array();
        foreach ($this as $row) {
          $textRow = array();
          foreach ($row as $k => $v) {
            $textRow[$k] = $v
              ->dumpValue('text');
            $width = strlen($textRow[$k]);
            if ($colWidths[$k] < $width) {
              $colWidths[$k] = $width;
            }
          }
          $textData[] = $textRow;
        }

        // Create a horizontal rule
        $hr = "+";
        foreach ($colWidths as $k => $v) {
          $hr .= "-" . str_repeat('-', $v) . '-+';
        }

        // Output the field names
        $result .= "{$hr}\n|";
        foreach ($this->fields as $field) {
          $result .= ' ' . str_pad("?{$field}", $colWidths[$field]) . ' |';
        }

        // Output each of the rows
        $result .= "\n{$hr}\n";
        foreach ($textData as $textRow) {
          $result .= '|';
          foreach ($textRow as $k => $v) {
            $result .= ' ' . str_pad($v, $colWidths[$k]) . ' |';
          }
          $result .= "\n";
        }
        $result .= "{$hr}\n";
      }
      return $result;
    }
    elseif ($this->type == 'boolean') {
      $str = $this->boolean ? 'true' : 'false';
      if ($format == 'html') {
        return "<p>Result: <span style='font-weight:bold'>{$str}</span></p>";
      }
      else {
        return "Result: {$str}";
      }
    }
    else {
      throw new EasyRdf_Exception("Failed to dump SPARQL Query Results format, unknown type: " . $this->type);
    }
  }

  /** Create a new EasyRdf_Resource or EasyRdf_Literal depending
   *  on the type of data passed in.
   *
   * @ignore
   */
  protected function newTerm($data) {
    switch ($data['type']) {
      case 'bnode':
        return new EasyRdf_Resource('_:' . $data['value']);
      case 'uri':
        return new EasyRdf_Resource($data['value']);
      case 'literal':
      case 'typed-literal':
        return EasyRdf_Literal::create($data);
      default:
        throw new EasyRdf_Exception("Failed to parse SPARQL Query Results format, unknown term type: " . $data['type']);
    }
  }

  /** Parse a SPARQL result in the XML format into the object.
   *
   * @ignore
   */
  protected function parseXml($data) {
    $doc = new DOMDocument();
    $doc
      ->loadXML($data);

    # Check for valid root node.
    if ($doc
      ->hasChildNodes() == false or $doc->childNodes->length != 1 or $doc->firstChild->nodeName != 'sparql' or $doc->firstChild->namespaceURI != self::SPARQL_XML_RESULTS_NS) {
      throw new EasyRdf_Exception("Incorrect root node in SPARQL XML Query Results format");
    }

    # Is it the result of an ASK query?
    $boolean = $doc
      ->getElementsByTagName('boolean');
    if ($boolean->length) {
      $this->type = 'boolean';
      $value = $boolean
        ->item(0)->nodeValue;
      $this->boolean = $value == 'true' ? true : false;
      return;
    }

    # Get a list of variables from the header
    $head = $doc
      ->getElementsByTagName('head');
    if ($head->length) {
      $variables = $head
        ->item(0)
        ->getElementsByTagName('variable');
      foreach ($variables as $variable) {
        $this->fields[] = $variable
          ->getAttribute('name');
      }
    }

    # Is it the result of a SELECT query?
    $resultstag = $doc
      ->getElementsByTagName('results');
    if ($resultstag->length) {
      $this->type = 'bindings';
      $results = $resultstag
        ->item(0)
        ->getElementsByTagName('result');
      foreach ($results as $result) {
        $bindings = $result
          ->getElementsByTagName('binding');
        $t = new stdClass();
        foreach ($bindings as $binding) {
          $key = $binding
            ->getAttribute('name');
          foreach ($binding->childNodes as $node) {
            if ($node->nodeType != XML_ELEMENT_NODE) {
              continue;
            }
            $t->{$key} = $this
              ->newTerm(array(
              'type' => $node->nodeName,
              'value' => $node->nodeValue,
              'lang' => $node
                ->getAttribute('xml:lang'),
              'datatype' => $node
                ->getAttribute('datatype'),
            ));
            break;
          }
        }
        $this[] = $t;
      }
      return $this;
    }
    throw new EasyRdf_Exception("Failed to parse SPARQL XML Query Results format");
  }

  /** Parse a SPARQL result in the JSON format into the object.
   *
   * @ignore
   */
  protected function parseJson($data) {

    // Decode JSON to an array
    $data = json_decode($data, true);
    if (isset($data['boolean'])) {
      $this->type = 'boolean';
      $this->boolean = $data['boolean'];
    }
    elseif (isset($data['results'])) {
      $this->type = 'bindings';
      if (isset($data['head']['vars'])) {
        $this->fields = $data['head']['vars'];
      }
      foreach ($data['results']['bindings'] as $row) {
        $t = new stdClass();
        foreach ($row as $key => $value) {
          $t->{$key} = $this
            ->newTerm($value);
        }
        $this[] = $t;
      }
    }
    else {
      throw new EasyRdf_Exception("Failed to parse SPARQL JSON Query Results format");
    }
  }

  /** Magic method to return value of the result to string
   *
   * If this is a boolean result then it will return 'true' or 'false'.
   * If it is a bindings type, then it will dump as a text based table.
   *
   * @return string A string representation of the result.
   */
  public function __toString() {
    if ($this->type == 'boolean') {
      return $this->boolean ? 'true' : 'false';
    }
    else {
      return $this
        ->dump('text');
    }
  }

}

Classes

Namesort descending Description
EasyRdf_Sparql_Result Class for returned for SPARQL SELECT and ASK query responses.