Location: PHPKode > projects > ArangoDB-PHP > ArangoDB-PHP-1.0.1/lib/triagens/ArangoDb/Document.php
<?php

/**
 * ArangoDB PHP client: single document 
 * 
 * @package ArangoDbPhpClient
 * @author Jan Steemann
 * @copyright Copyright 2012, triagens GmbH, Cologne, Germany
 */

namespace triagens\ArangoDb;

/**
 * Value object representing a single collection-based document
 *
 * @package ArangoDbPhpClient
 */
class Document {
  /**
   * The document id (might be NULL for new documents)
   * @var string - document id
   */
  protected $_id      = NULL;
  
  /**
   * The document revision (might be NULL for new documents)
   * @var mixed
   */
  protected $_rev     = NULL;
  
  /**
   * The document attributes (names/values)
   * @var array
   */
  protected $_values  = array();

  /**
   * Flag to indicate whether document was changed locally
   * @var bool
   */
  protected $_changed;
  
  /**
   * Flag to indicate whether document was changed locally
   * @var bool
   */
  protected $_hidden = array();

  /**
   * Document id index
   */
  const ENTRY_ID    = '_id';
  
  /**
   * Revision id index
   */
  const ENTRY_REV   = '_rev';

 /**
   * hidden atttribute index
   */
  const ENTRY_HIDDEN   = '_hidden';

  /**
   * Constructs an empty document
   *
   * @param array $options - optional, initial $options for document
   * @return void
   */
  public function __construct(array $options = array()) {
    $this->setChanged(false);
    if (array_key_exists('hiddenAttributes',$options))$this->setHiddenAttributes($options['hiddenAttributes']);
  }

  /**
   * Factory method to construct a new document using the values passed to populate it
   *
   * @throws ClientException
   * @param array $values - initial values for document
   * @param array $options - optional, initial options for document
   * @return Document
   */
  public static function createFromArray(array $values, array $options = array()) {
    $document = new static($options);
    
    foreach ($values as $key => $value) {
      $document->set($key, $value);
    }

    $document->setChanged(true);

    return $document;
  }
  
  /**
   * Clone a document
   * 
   * Returns the clone 
   *
   * @return void
   */
  public function __clone() {
    $this->_id = NULL;
    $this->_rev = NULL;

    // do not change the _changed flag here
  }
  
  /**
   * Get a string representation of the document.
   * 
   * It will not output hidden attributes.
   * 
   * Returns the document as JSON-encoded string
   *
   * @return string - JSON-encoded document 
   */
  public function __toString() {
    return $this->toJson();
  }
  
  /**
   * Returns the document as JSON-encoded string
   * 
   * @param array $options - optional, array of options that will be passed to the getAll function
   * <p>Options are : 
   * <li>'includeInternals' - true to include the internal attributes. Defaults to false</li>
   * <li>'ignoreHiddenAttributes' - true to show hidden attributes. Defaults to false</li>
   * </p>
   * 
   * @return string - JSON-encoded document 
   */
  public function toJson($options=array()) {
    return json_encode($this->getAll($options));
  }
  
  /**
   * Returns the document as a serialized string
   * 
   * @param array $options - optional, array of options that will be passed to the getAll function
   * <p>Options are : 
   * <li>'includeInternals' - true to include the internal attributes. Defaults to false</li>
   * <li>'ignoreHiddenAttributes' - true to show hidden attributes. Defaults to false</li>
   * </p>
   * 
   * @return string - PHP serialized document 
   */
  public function toSerialized($options=array()) {
    return serialize($this->getAll($options));
  }

  /**
   * Returns the attributes with the hidden ones removed
   *
   * @param array - attributes array 
   * @return array - attributes array 
   */
  public function filterHiddenAttributes($attributes) {
    $hiddenAttributes=$this->getHiddenAttributes();
        
    if (is_array($hiddenAttributes)) {
      foreach ($hiddenAttributes as $hiddenAttributeName) {
        if (!in_array($hiddenAttributeName, $attributes)) {
            unset ($attributes[$hiddenAttributeName]);
        }
      }
    }
    
    unset ($attributes['_hidden']);
    
    return $attributes;
  }
  /**
   * Set a document attribute
   *
   * The key (attribute name) must be a string.
   * This will validate the value of the attribute and might throw an
   * exception if the value is invalid.
   *
   * @throws ClientException
   * @param string $key - attribute name
   * @param mixed $value - value for attribute
   * @return void
   */
  public function set($key, $value) {
    if (!is_string($key)) {
      throw new ClientException('Invalid document attribute key');
    }

    // validate the value passed
    ValueValidator::validate($value);

    if ($key === self::ENTRY_ID) {
      $this->setInternalId($value);
      return;
    }
    
    if ($key === self::ENTRY_REV) {
      $this->setRevision($value);
      return;
    }

    if (!$this->_changed) {
      if (!isset($this->_values[$key]) || $this->_values[$key] !== $value) {
        // set changed flag
        $this->_changed = true;
      }
    }

    // and store the value
    $this->_values[$key] = $value;
  }
  
  /**
   * Set a document attribute, magic method
   *
   * This is a magic method that allows the object to be used without
   * declaring all document attributes first.
   * This function is mapped to set() internally.
   *
   * @throws ClientException
   * @param string $key - attribute name
   * @param mixed $value - value for attribute
   * @return void
   */
  public function __set($key, $value) {
    $this->set($key, $value);
  }

  /**
   * Get a document attribute
   *
   * @param string $key - name of attribute
   * @return mixed - value of attribute, NULL if attribute is not set
   */
  public function get($key) {
    if (isset($this->_values[$key])) {
      return $this->_values[$key];
    }

    return NULL;
  }

  /**
   * Get a document attribute, magic method
   * 
   * This function is mapped to get() internally.
   *
   * @param string $key - name of attribute
   * @return mixed - value of attribute, NULL if attribute is not set
   */
  public function __get($key) {
    return $this->get($key);
  }
  
  /**
   * Get all document attributes
   *
   * @param mixed $options - optional, array of options for the getAll function, or the boolean value for $includeInternals
   * <p>Options are : 
   * <li>'includeInternals' - true to include the internal attributes. Defaults to false</li>
   * <li>'ignoreHiddenAttributes' - true to show hidden attributes. Defaults to false</li>
   * </p>
   * @return array - array of all document attributes/values
   */
  public function getAll($options=array()) {
    // This preserves compatibility for the old includeInternals parameter.
    $includeInternals = false;
    $ignoreHiddenAttributes = false;

    if (!is_array($options)){
      $includeInternals = $options;
    }else{
      $includeInternals = array_key_exists('includeInternals',$options) ? $options['includeInternals'] : $includeInternals;
      $ignoreHiddenAttributes = array_key_exists('ignoreHiddenAttributes',$options) ? $options['ignoreHiddenAttributes'] : $ignoreHiddenAttributes;
    }
    
    $data=$this->_values;
    $nonInternals=array('_changed', '_values', '_hidden');
    
    if ($includeInternals == true) {
      foreach ($this as $key => $value) {
        if (substr($key,0,1) == '_' && substr($key,0,2) !== '__' && !in_array($key, $nonInternals)) {
            $data[$key] = $value;        
        }
      }
    }
    
    if ($ignoreHiddenAttributes==false) {
      $data=$this->filterHiddenAttributes($data);
    }
    
    return $data;
  }
  
  /**
   * Set the hidden attributes
   * 
   * @param array $attributes - array of attributes
   * @return void
   */
  public function setHiddenAttributes(array $attributes) {
    $this->_hidden = $attributes;
  }
  
  /**
   * Get the hidden attributes
   * 
   * @return array $attributes - array of attributes
   */
  public function getHiddenAttributes() {
    return $this->_hidden;
  }
  
  /**
   * Set the changed flag
   *
   * @param bool $value - change flag
   * @return void
   */
  public function setChanged($value) {
    return $this->_changed = (bool) $value;
  }
  
  /**
   * Get the changed flag
   *
   * @return bool - true if document was changed, false otherwise
   */
  public function getChanged() {
    return $this->_changed;
  }
  
  /**
   * Set the internal document id 
   * 
   * This will throw if the id of an existing document gets updated to some other id
   *
   * @throws ClientException
   * @param string $id - internal document id
   * @return void
   */
  public function setInternalId($id) {
    if ($this->_id !== NULL && $this->_id != $id) {
      throw new ClientException('Should not update the id of an existing document');
    }

    if (!preg_match('/^\d+\/\d+$/', $id)) {
      throw new ClientException('Invalid format for document id');
    }

    $this->_id = $id;
  }

  /**
   * Get the internal document id (if already known)
   * 
   * Document ids are generated on the server only. Document ids consist of collection id and
   * document id, in the format collectionid/documentid
   *
   * @return string - internal document id, might be NULL if document does not yet have an id
   */
  public function getInternalId() {
    return $this->_id; 
  }
  
  /**
   * Convenience function to get the document handle (if already known) - is an alias to getInternalId()
   * 
   * Document handles are generated on the server only. Document handles consist of collection id and
   * document id, in the format collectionid/documentid
   *
   * @return string - internal document id, might be NULL if document does not yet have an id
   */
  public function getHandle() {
    return $this->getInternalId(); 
  }
  
  /**
   * Get the document id (if already known)
   * 
   * Document ids are generated on the server only. Document ids are numeric but might be
   * bigger than PHP_INT_MAX. To reliably store a document id elsewhere, a PHP string should be used 
   *
   * @return mixed - document id, might be NULL if document does not yet have an id
   */
  public function getId() {
    @list(, $documentId) = explode('/', $this->_id, 2);

    return $documentId;
  }
  
  /**
   * Get the collection id (if already known)
   * 
   * Collection ids are generated on the server only. Collection ids are numeric but might be
   * bigger than PHP_INT_MAX. To reliably store a collection id elsewhere, a PHP string should be used 
   *
   * @return mixed - collection id, might be NULL if document does not yet have an id
   */
  public function getCollectionId() {
    @list($collectionId) = explode('/', $this->_id, 2);

    return $collectionId;
  }
  
  /**
   * Set the document revision
   * 
   * Revision ids are generated on the server only. 
   * 
   * Document ids are numeric but might be bigger than PHP_INT_MAX. 
   * To reliably store a document id elsewhere, a PHP string should be used 
   *
   * @param mixed $rev - revision id
   * @return void
   */
  public function setRevision($rev) {
    $this->_rev = $rev;
  }
  
  /**
   * Get the document revision (if already known)
   *
   * @return mixed - revision id, might be NULL if document does not yet have an id
   */
  public function getRevision() {
    return $this->_rev;
  }

}
Return current item: ArangoDB-PHP