dbscript
[ class tree: dbscript ] [ index: dbscript ] [ all elements ]

Source for file database.php

Documentation is available at database.php

  1. <?php
  2.  
  3.   /** 
  4.    * dbscript for PHP 4 & 5 - restful crud framework
  5.    * @version 0.1.2 -- 19-Feb-2007
  6.    * @author Brian Hendrickson <brian@dbscript.net>
  7.    * @link http://dbscript.net/
  8.    * @copyright Copyright 2007 Brian Hendrickson
  9.    * @package dbscript
  10.    * @license http://www.opensource.org/licenses/mit-license.php MIT License
  11.    */
  12.  
  13.   /**
  14.    * Database
  15.    * 
  16.    * Connects to the database, fetches records
  17.    * into data objects and performs CRUD operations.
  18.    * 
  19.    * Usage:
  20.    * <code>
  21.    * $db = new PostgreSQL(
  22.    *   'host',
  23.    *   'db',
  24.    *   'user'
  25.    * );
  26.    * </code>
  27.    * 
  28.    * More info...
  29.    * {@link http://dbscript.net/database}
  30.    * 
  31.    * @package dbscript
  32.    * @author Brian Hendrickson <brian@dbscript.net>
  33.    * @access public
  34.    * @version 0.1.2
  35.    */
  36.  
  37. class Database {
  38.   
  39.   /**
  40.    * connection resource used to access the database
  41.    * @var resource 
  42.    */
  43.   var $conn;
  44.   
  45.   /**
  46.    * true if the database is connected
  47.    * @var bool 
  48.    */
  49.   var $db_open;
  50.  
  51.   /**
  52.    * array of data models
  53.    * @var Model[] 
  54.    */
  55.   var $models;
  56.  
  57.   /**
  58.    * array of recordsets
  59.    * @var RecordSet[] 
  60.    */
  61.   var $recordsets;
  62.  
  63.   /**
  64.    * tables
  65.    * @var tables 
  66.    */
  67.   var $tables;
  68.   
  69.   /**
  70.    * maximum binary file size
  71.    * @var integer 
  72.    */
  73.  
  74.   /**
  75.    * maximum string length
  76.    * @var integer 
  77.    */
  78.  
  79.   /**
  80.    * poss. values for boolean true
  81.    * @var string[] 
  82.    */
  83.   var $true_values;
  84.  
  85.   /**
  86.    * datatype groupings
  87.    * @var string[] 
  88.    */
  89.   var $datatype_map;
  90.   
  91.   /**
  92.    * Get Record
  93.    * 
  94.    * return a Record object for the named table
  95.    * 
  96.    * @author Brian Hendrickson <brian@dbscript.net>
  97.    * @access public
  98.    * @param string table
  99.    * @return Record 
  100.    */
  101.   function get_record($table{
  102.     $func_args func_get_args();
  103.     if (count($func_args&& count($func_args4{
  104.       if (isset($func_args[2])) {
  105.         return new Record($table,$this,$func_args[1],$func_args[2]);
  106.       elseif (isset($func_args[1])) {
  107.         return new Record($table,$this,$func_args[1]);
  108.       else {
  109.         return new Record($table,$this);
  110.       }
  111.     else {
  112.       return false;
  113.     }
  114.   }
  115.  
  116.   /**
  117.    * Iterate Record
  118.    * 
  119.    * return a Record object from the Model's active result set
  120.    * 
  121.    * @author Brian Hendrickson <brian@dbscript.net>
  122.    * @access public
  123.    * @param string table
  124.    * @param string[] fields
  125.    * @param recordset rs
  126.    * @param integer id
  127.    * @return Record 
  128.    */  
  129.   function iterator_load_record($table,$fields,$rs,$id=NULL{
  130.     trigger_before'iterator_load_record'$this$rs );
  131.     if ($this->models[$table]->custom_class{
  132.       $custom_class $this->models[$table]->custom_class;
  133.       $rec new $custom_class$this->models[$table);
  134.       if (!$rectrigger_error"error instantiating $custom_class"E_USER_ERROR );
  135.       $rec->Record($table,$this);
  136.       foreach ($rec->relationships as $key=>$val{
  137.         $this->models[$table]->set_relation$key$val );
  138.       }
  139.     else {
  140.       $rec $this->get_record($table);
  141.     }
  142.     if isset$rs->relations[$fields[$rec->primary_key]] ) ) {
  143.       foreach $rs->relations[$fields[$rec->primary_key]] as $reltable=>$relpkvalue {
  144.         $rec->children[$reltable$relpkvalue;
  145.       }
  146.     }
  147.     $rec->attributes[$rec->primary_key$fields[$rec->primary_key];
  148.     $primary_key $rec->primary_key;
  149.     $rec->$primary_key =$rec->attributes[$rec->primary_key];
  150.     $this->set_attributes($rec,$fields);
  151.     trigger_after'iterator_load_record'$this$rec );
  152.     return $rec;
  153.   }
  154.  
  155.   /**
  156.    * Get RecordSet
  157.    * 
  158.    * return a multi-graph RecordSet from a SQORP-formatted SQL join query
  159.    * 
  160.    * @author Brian Hendrickson <brian@dbscript.net>
  161.    * @access public
  162.    * @param string sql
  163.    * @return RecordSet 
  164.    */  
  165.   function get_recordset($sql{
  166.     return new RecordSet($sql,$this);
  167.   }
  168.  
  169.   /**
  170.    * Get Inline Url
  171.    * 
  172.    * deprecated
  173.    * 
  174.    * @author Brian Hendrickson <brian@dbscript.net>
  175.    * @access public
  176.    * @param string[] blob_location
  177.    * @param string content_type
  178.    * @return string 
  179.    */  
  180.   function get_inline_url($blob_location,$content_type{
  181.     $url "?action=get_file";
  182.     if (is_array($blob_location)) {
  183.       $url .= "&i=" $blob_location['id'];
  184.       $url .= "&k=" $blob_location['primary_key'];
  185.       $url .= "&t=" $blob_location['table'];
  186.       $url .= "&f=" $blob_location['field'];
  187.     else {
  188.       $url .= "&o=" $blob_location;
  189.     }
  190.     $url .= "&c=" urlencode($content_type);
  191.     return $url;
  192.   }
  193.  
  194.   /**
  195.    * Max Upload Megabytes
  196.    * 
  197.    * set the file upload size limit
  198.    * 
  199.    * @author Brian Hendrickson <brian@dbscript.net>
  200.    * @access public
  201.    * @param integer megabytes
  202.    */ 
  203.   function max_upload_megabytes$megabytes {
  204.     $this->max_blob_length = $megabytes 1024000 );
  205.   }
  206.   
  207.   /**
  208.    * Skeletor
  209.    * 
  210.    * create a skeleton from an existing Record
  211.    * 
  212.    * @author Brian Hendrickson <brian@dbscript.net>
  213.    * @access public
  214.    * @param Record rec
  215.    * @return Record 
  216.    */ 
  217.   function skeletor(&$rec{
  218.     $table $rec->table;
  219.     $pk $rec->primary_key;
  220.     $fields array();
  221.     foreach ($rec->attributes as $key=>$val{
  222.       $fields[$key"";
  223.     }
  224.     $fields[$rec->primary_key0;
  225.     $skeleton $this->get_record($table);
  226.     $skeleton->is_skeleton();
  227.     $this->set_attributes($skeleton,$fields);
  228.     return $skeleton;
  229.   }
  230.   
  231.   /**
  232.    * Distinct Values
  233.    * 
  234.    * set the file upload size limit
  235.    * 
  236.    * @author Brian Hendrickson <brian@dbscript.net>
  237.    * @access public
  238.    * @param string table
  239.    * @param string field
  240.    * @param string orderby
  241.    * @return string[] 
  242.    */
  243.   function distinct_values$table$field$orderby="" {
  244.     $values array();
  245.     if (!(strlen($orderby0)) $orderby $field}
  246.     $sql $this->select_distinct$field$table$orderby );
  247.     $result $this->get_result($sql);
  248.     if (!($this->num_rows($result0)) {
  249.       return false;
  250.     }
  251.     while $row $this->fetch_array$result ) ) {
  252.       $values[$row[$this->models[$table]->primary_key]] $row[$field];
  253.     }
  254.     return $values;
  255.   }
  256.   
  257.   /**
  258.    * Fetch Record
  259.    * 
  260.    * set the file upload size limit
  261.    * 
  262.    * @author Brian Hendrickson <brian@dbscript.net>
  263.    * @access public
  264.    * @param Record rec
  265.    * @param integer id
  266.    */
  267.   function fetch_record(&$rec,$id{
  268.     trigger_before'fetch_record'$this$rec );
  269.     $sql $this->sql_select_for$rec$id );
  270.     $result $this->get_result($sql);
  271.     if (!($this->num_rows($result0)) {
  272.       return false;
  273.     }
  274.     $pkfield $rec->primary_key;
  275.     $rec->attributes[$pkfield$id;
  276.     $rec->$pkfield $id;
  277.     $field_array $this->fetch_array($result);
  278.     $this->set_attributes($rec,$field_array);
  279.     trigger_after'fetch_record'$this$rec );
  280.   }
  281.  
  282.   /**
  283.    * Get Mapped Datatype
  284.    * 
  285.    * return the abstract type for a given native type
  286.    * 
  287.    * @author Brian Hendrickson <brian@dbscript.net>
  288.    * @access public
  289.    * @param string raw_datatype
  290.    * @param string 
  291.    */
  292.   function get_mapped_datatype$raw_datatype {
  293.     if (strstr($raw_datatype,"(")) {
  294.       $raw_datatype substr($raw_datatype0strpos($raw_datatype,"("));
  295.     }
  296.     if (array_key_exists$raw_datatype$this->datatype_map )) {
  297.       return $this->datatype_map[$raw_datatype];
  298.     else {
  299.       if (ignore_errors()) return 'char';
  300.       trigger_error"Errorthe $raw_datatype datatype is not listed in dbscript's datatype map."E_USER_NOTICE );
  301.     }
  302.   }
  303.  
  304.   /**
  305.    * Get Objects
  306.    * 
  307.    * return the data model objects in an array
  308.    * 
  309.    * @author Brian Hendrickson <brian@dbscript.net>
  310.    * @access public
  311.    * @return Model[] 
  312.    */
  313.   function &get_objects({
  314.     $objects array();
  315.     $skip array'.''..' );
  316.     if $handle opendirmodel_path() )) {
  317.       while false !== $file readdir$handle ))) {
  318.         if (!(in_array($file$skip)) && substr$file-== '.php' {
  319.           $o substr$file0-);
  320.           $objects[$o=$this->get_tabletableize($o) );
  321.         }
  322.       }
  323.       foreach($objects as $name=>$model)
  324.         $model->save();
  325.       closedir($handle);
  326.     }
  327.     return $objects;
  328.   }
  329.  
  330.  
  331.   /**
  332.    * Table Exists
  333.    * 
  334.    * return whether a table exists
  335.    * 
  336.    * @author Brian Hendrickson <brian@dbscript.net>
  337.    * @access public
  338.    * @return Model[] 
  339.    */
  340.   function table_exists$table {
  341.     return isset$this->data_models[$table);
  342.   }
  343.   
  344.   
  345.   /**
  346.    * Set Data Array
  347.    * 
  348.    * populate a data object's attributes array
  349.    * 
  350.    * @author Brian Hendrickson <brian@dbscript.net>
  351.    * @access public
  352.    * @param Record rec
  353.    * @param string[] fields
  354.    */
  355.   function set_attributes(&$rec,&$fields{
  356.     foreach ($fields as $field=>$value{
  357.       if ($field == $rec->primary_key && $value == ""$value 0;
  358.       if (!is_numeric($field)) {
  359.         $datatype $this->get_mapped_datatype($this->models[$rec->table]->field_array[$field]);
  360.         if ($datatype == 'blob'{
  361.           $value $this->blob_value$rec$field$value )// oid (pgsql) or array (mysql)
  362.         }
  363.         if ($datatype == 'bool'{
  364.           if in_array$value$this->true_valuestrue ) ) {
  365.             $value true;
  366.           else {
  367.             $value false;
  368.           }
  369.         }
  370.         $rec->attributes[$field$value;
  371.         if !isset$rec->$field ) ) )
  372.           $rec->$field =$rec->attributes[$field];
  373.       }
  374.     }
  375.     if (!(in_array($rec->attributes[$rec->primary_key]array('',0)true)))
  376.       $rec->exists true;
  377.     $rec->table $rec->table;
  378.     $rec->exists $rec->exists;
  379.   }
  380.   
  381.   function primary_key_for$table {
  382.     if (!(isset($this->models[$table]))) {
  383.       $fields $this->get_fields$table );
  384.       if (isset($fields[$table."_primary_key"]))
  385.         $pk $fields[$table."_primary_key"];
  386.       else
  387.         $pk 'id';
  388.     else {
  389.       $pk $this->models[$table]->primary_key;
  390.     }
  391.     return $pk;
  392.   }
  393.   
  394.   /**
  395.    * Save Record
  396.    * 
  397.    * save a record's attributes into the database
  398.    * 
  399.    * @author Brian Hendrickson <brian@dbscript.net>
  400.    * @access public
  401.    * @param Record rec
  402.    */
  403.   function save_record&$rec {
  404.     trigger_before'save_record'$rec$this->models[$rec->table);
  405.     if !$rec->modified_fields && $rec->exists )) {
  406.       return true// nothing to save!
  407.     }
  408.     if $rec->exists {
  409.       // update
  410.       if array_key_exists'last_modified'$rec->attributes ))
  411.         $rec->set_value'last_modified'timestamp() );
  412.       if array_key_exists'modified_at'$rec->attributes ))
  413.         $rec->set_value'modified_at'timestamp() );
  414.       if array_key_exists'modified'$rec->attributes ))
  415.         $rec->set_value'modified'timestamp() );
  416.       if array_key_exists'access_time'$rec->attributes ))
  417.         $rec->set_value'access_time'timestamp() );
  418.       $result $this->get_result$this->sql_update_for$rec ));
  419.     else {
  420.       // insert
  421.       if array_key_exists'created_at'$rec->attributes ))
  422.         $rec->set_value'created_at'timestamp() );
  423.       if array_key_exists'created'$rec->attributes ))
  424.         $rec->set_value'created'timestamp() );
  425.       if array_key_exists'issued'$rec->attributes ))
  426.         $rec->set_value'issued'timestamp() );
  427.       $result $this->get_result$this->sql_insert_for$rec ));
  428.       $this->post_insert$rec$result );
  429.     }
  430.     $rec->exists true;
  431.     $rec->modified_fields array();
  432.     trigger_after'save_record'$rec$this$this->models[$rec->table);
  433.     return true;
  434.   }
  435.  
  436.   /**
  437.    * Delete Record
  438.    * 
  439.    * save a record's attributes into the database
  440.    * 
  441.    * @author Brian Hendrickson <brian@dbscript.net>
  442.    * @access public
  443.    * @param Record rec
  444.    * @return boolean 
  445.    */
  446.   function delete_record&$rec {
  447.     $return false;
  448.     trigger_before'delete_record'$this$rec );
  449.     if ($rec->exists{
  450.       if (strlen($rec->attributes[$rec->primary_key]0{
  451.         $result $this->get_result$this->sql_delete_for$rec ) );
  452.       }
  453.       if (!$result{
  454.         $return false;
  455.       else {
  456.         $rec->exists false;
  457.         $return true;
  458.       }
  459.     }
  460.     trigger_after'delete_record'$this$rec );
  461.     return $return;
  462.   }
  463.  
  464. }
  465.  
  466. ?>

Documentation generated on Mon, 19 Feb 2007 10:24:45 -0800 by phpDocumentor 1.3.1