Location: PHPKode > projects > Dbscript > db/library/dbscript/database.php
<?php

  /** 
   * dbscript for PHP 4 & 5 - restful crud framework
   * @version 0.3.0 -- 10-Jun-2007
   * @author Brian Hendrickson <hide@address.com>
   * @link http://dbscript.net/
   * @copyright Copyright 2007 Brian Hendrickson
   * @package dbscript
   * @license http://www.opensource.org/licenses/mit-license.php MIT License
   */

  /**
   * Database
   * 
   * Connects to the database, fetches records
   * into data objects and performs CRUD operations.
   * 
   * Usage:
   * <code>
   * $db = new PostgreSQL(
   *   'host',
   *   'db',
   *   'user'
   * );
   * </code>
   * 
   * More info...
   * {@link http://dbscript.net/database}
   * 
   * @package dbscript
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @version 0.3.0
   */

class Database {
  
  /**
   * connection resource used to access the database
   * @var resource
   */
  var $conn;
  
  /**
   * true if the database is connected
   * @var bool
   */
  var $db_open;

  /**
   * array of data models
   * @var Model[]
   */
  var $models;

  /**
   * array of recordsets
   * @var RecordSet[]
   */
  var $recordsets;

  /**
   * tables
   * @var tables
   */
  var $tables;
  
  /**
   * maximum binary file size
   * @var integer
   */
  var $max_blob_length;

  /**
   * maximum string length
   * @var integer
   */
  var $max_string_length;

  /**
   * poss. values for boolean true
   * @var string[]
   */
  var $true_values;

  /**
   * datatype groupings
   * @var string[]
   */
  var $datatype_map;
  
  /**
   * Get Record
   * 
   * return a Record object for the named table
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param string table
   * @return Record
   */
  function get_record($table) {
    $func_args = func_get_args();
    if (count($func_args) > 0 && count($func_args) < 4) {
      if (isset($func_args[2])) {
        return new Record($table,$this,$func_args[1],$func_args[2]);
      } elseif (isset($func_args[1])) {
        return new Record($table,$this,$func_args[1]);
      } else {
        return new Record($table,$this);
      }
    } else {
      return false;
    }
  }

  /**
   * Iterate Record
   * 
   * return a Record object from the Model's active result set
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param string table
   * @param string[] fields
   * @param recordset rs
   * @param integer id
   * @return Record
   */  
  function iterator_load_record($table,$fields,$rs,$id=NULL) {
    trigger_before( 'iterator_load_record', $this, $rs );
    if ($this->models[$table]->custom_class) {
      $custom_class = $this->models[$table]->custom_class;
      $rec = new $custom_class( $this->models[$table] );
      if (!$rec) trigger_error( "error instantiating $custom_class", E_USER_ERROR );
      $rec->Record($table,$this);
      foreach ($rec->relationships as $key=>$val) {
        $this->models[$table]->set_relation( $key, $val );
      }
    } else {
      $rec = $this->get_record($table);
    }
    if ( isset( $rs->relations[$fields[$rec->primary_key]] ) ) {
      foreach ( $rs->relations[$fields[$rec->primary_key]] as $reltable=>$relpkvalue ) {
        $rec->children[$reltable] = $relpkvalue;
      }
    }
    $rec->attributes[$rec->primary_key] = $fields[$rec->primary_key];
    $primary_key = $rec->primary_key;
    $rec->$primary_key =& $rec->attributes[$rec->primary_key];
    $this->set_attributes($rec,$fields);
    trigger_after( 'iterator_load_record', $this, $rec );
    return $rec;
  }

  /**
   * Get RecordSet
   * 
   * return a multi-graph RecordSet from a SQORP-formatted SQL join query
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param string sql
   * @return RecordSet
   */  
  function get_recordset($sql) {
    return new RecordSet($sql,$this);
  }

  /**
   * Get Inline Url
   * 
   * deprecated
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param string[] blob_location
   * @param string content_type
   * @return string
   */  
  function get_inline_url($blob_location,$content_type) {
    $url = "?action=get_file";
    if (is_array($blob_location)) {
      $url .= "&i=" . $blob_location['id'];
      $url .= "&k=" . $blob_location['primary_key'];
      $url .= "&t=" . $blob_location['table'];
      $url .= "&f=" . $blob_location['field'];
    } else {
      $url .= "&o=" . $blob_location;
    }
    $url .= "&c=" . urlencode($content_type);
    return $url;
  }

  /**
   * Max Upload Megabytes
   * 
   * set the file upload size limit
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param integer megabytes
   */ 
  function max_upload_megabytes( $megabytes ) {
    $this->max_blob_length = ( $megabytes * 1024000 );
  }
  
  /**
   * Skeletor
   * 
   * create a skeleton from an existing Record
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param Record rec
   * @return Record
   */ 
  function skeletor(&$rec) {
    $table = $rec->table;
    $pk = $rec->primary_key;
    $fields = array();
    foreach ($rec->attributes as $key=>$val) {
      $fields[$key] = "";
    }
    $fields[$rec->primary_key] = 0;
    $skeleton = $this->get_record($table);
    $skeleton->is_skeleton();
    $this->set_attributes($skeleton,$fields);
    return $skeleton;
  }
  
  /**
   * Distinct Values
   * 
   * set the file upload size limit
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param string table
   * @param string field
   * @param string orderby
   * @return string[]
   */
  function distinct_values( $table, $field, $orderby="" ) {
    $values = array();
    if (!(strlen($orderby) > 0)) { $orderby = $field; }
    $sql = $this->select_distinct( $field, $table, $orderby );
    $result = $this->get_result($sql);
    if (!($this->num_rows($result) > 0)) {
      return false;
    }
    while ( $row = $this->fetch_array( $result ) ) {
      $values[$row[$this->models[$table]->primary_key]] = $row[$field];
    }
    return $values;
  }
  
  /**
   * Fetch Record
   * 
   * set the file upload size limit
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param Record rec
   * @param integer id
   */
  function fetch_record(&$rec,$id) {
    trigger_before( 'fetch_record', $this, $rec );
    $sql = $this->sql_select_for( $rec, $id );
    $result = $this->get_result($sql);
    if (!($this->num_rows($result) > 0)) {
      return false;
    }
    $pkfield = $rec->primary_key;
    $rec->attributes[$pkfield] = $id;
    $rec->$pkfield = $id;
    $field_array = $this->fetch_array($result);
    $this->set_attributes($rec,$field_array);
    trigger_after( 'fetch_record', $this, $rec );
  }

  /**
   * Get Mapped Datatype
   * 
   * return the abstract type for a given native type
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param string raw_datatype
   * @param string
   */
  function get_mapped_datatype( $raw_datatype ) {
    if (strstr($raw_datatype,"(")) {
      $raw_datatype = substr($raw_datatype, 0, strpos($raw_datatype,"("));
    }
    if (array_key_exists( $raw_datatype, $this->datatype_map )) {
      return $this->datatype_map[$raw_datatype];
    } else {
      if (ignore_errors()) return 'char';
      trigger_error( "Error, the $raw_datatype datatype is not listed in dbscript's datatype map.", E_USER_NOTICE );
    }
  }

  /**
   * Get Objects
   * 
   * return the data model objects in an array
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @return Model[]
   */
  function &get_objects() {
    $objects = array();
    $skip = array( '.', '..' );
    if ( $handle = opendir( model_path() )) {
      while ( false !== ( $file = readdir( $handle ))) {
        if (!(in_array($file, $skip)) && substr( $file, -4 ) == '.php' ) {
          $o = substr( $file, 0, -4 );
          $objects[$o] =& $this->get_table( tableize($o) );
        }
      }
      foreach( $objects as $name=>$model )
        $model->save();
      closedir($handle);
    }
    return $objects;
  }


  /**
   * Table Exists
   * 
   * return whether a table exists
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @return Model[]
   */
  function table_exists( $table ) {
    return isset( $this->data_models[$table] );
  }
  
  
  /**
   * Set Data Array
   * 
   * populate a data object's attributes array
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param Record rec
   * @param string[] fields
   */
  function set_attributes(&$rec,&$fields) {
    foreach ($fields as $field=>$value) {
      if ($field == $rec->primary_key && $value == "") $value = 0;
      if (!is_numeric($field)) {
        $datatype = $this->get_mapped_datatype($this->models[$rec->table]->field_array[$field]);
        if ($datatype == 'blob') {
          $value = $this->blob_value( $rec, $field, $value ); // oid (pgsql) or array (mysql)
        }
        if ($datatype == 'bool') {
          if ( in_array( $value, $this->true_values, true ) ) {
            $value = true;
          } else {
            $value = false;
          }
        }
        $rec->attributes[$field] = $value;
        if ( !( isset( $rec->$field ) ) )
          $rec->$field =& $rec->attributes[$field];
      }
    }
    if (!(in_array($rec->attributes[$rec->primary_key], array('',0), true)))
      $rec->exists = true;
    $rec->table = $rec->table;
    $rec->exists = $rec->exists;
  }
  
  function just_get_objects() {
    
    if ( isset( $_GET['dbscript_xml_error_continue'] )) {
      $this->get_objects();
      return true;
    }
    
    return false;
    
  }
  
  function primary_key_for( $table ) {
    if (!(isset($this->models[$table]))) {
      $fields = $this->get_fields( $table );
      if (isset($fields[$table."_primary_key"]))
        $pk = $fields[$table."_primary_key"];
      else
        $pk = 'id';
    } else {
      $pk = $this->models[$table]->primary_key;
    }
    return $pk;
  }
  
  /**
   * Save Record
   * 
   * save a record's attributes into the database
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param Record rec
   */
  function save_record( &$rec ) {
    trigger_before( 'save_record', $rec, $this->models[$rec->table] );
    if ( !$rec->modified_fields && ( $rec->exists )) {
      return true; // nothing to save!
    }
    if ( $rec->exists ) {
      // update
      if ( array_key_exists( 'last_modified', $rec->attributes ))
        $rec->set_value( 'last_modified', timestamp() );
      if ( array_key_exists( 'modified_at', $rec->attributes ))
        $rec->set_value( 'modified_at', timestamp() );
      if ( array_key_exists( 'modified', $rec->attributes ))
        $rec->set_value( 'modified', timestamp() );
      if ( array_key_exists( 'access_time', $rec->attributes ))
        $rec->set_value( 'access_time', timestamp() );
      $result = $this->get_result( $this->sql_update_for( $rec ));
    } else {
      // insert
      if ( array_key_exists( 'created_at', $rec->attributes ))
        $rec->set_value( 'created_at', timestamp() );
      if ( array_key_exists( 'created', $rec->attributes ))
        $rec->set_value( 'created', timestamp() );
      if ( array_key_exists( 'issued', $rec->attributes ))
        $rec->set_value( 'issued', timestamp() );
      $result = $this->get_result( $this->sql_insert_for( $rec ));
      $this->post_insert( $rec, $result );
    }
    $rec->exists = true;
    $rec->modified_fields = array();
    trigger_after( 'save_record', $rec, $this, $this->models[$rec->table] );
    return true;
  }

  /**
   * Delete Record
   * 
   * save a record's attributes into the database
   * 
   * @author Brian Hendrickson <hide@address.com>
   * @access public
   * @param Record rec
   * @return boolean
   */
  function delete_record( &$rec ) {
    $return = false;
    trigger_before( 'delete_record', $this, $rec );
    if ($rec->exists) {
      if (strlen($rec->attributes[$rec->primary_key]) > 0) {
        $result = $this->get_result( $this->sql_delete_for( $rec ) );
      }
      if (!$result) {
        $return = false;
      } else {
        $rec->exists = false;
        $return = true;
      }
    }
    trigger_after( 'delete_record', $this, $rec );
    return $return;
  }

}

?>
Return current item: Dbscript