Changeset 247 for trunk/trax/vendor

Show
Ignore:
Timestamp:
08/23/06 00:21:16 (6 years ago)
Author:
john
Message:

many bug fixes

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/trax/vendor/trax/active_record.php

    r241 r247  
    120120 
    121121    /** 
     122     *  Table prefix 
     123     * 
     124     *  Name to prefix to the $table_name. May be overridden. 
     125     *  @var string 
     126     */ 
     127    public $table_prefix = null; 
     128 
     129    /** 
    122130     *  Database name override 
    123131     * 
     
    154162     */ 
    155163    public $force_reconnect = false; # should we force a connection everytime 
    156      
    157     public $index_on = "id"; # find_all returns an array of objects each object index is off of this field 
    158      
    159     public $lock_optimistically = true; # page 222 Rails books 
     164 
     165    /** 
     166     *  find_all() returns an array of objects,  
     167     *  each object index is off of this field 
     168     * 
     169     *  @var boolean 
     170     */     
     171    public $index_on = "id";  
     172 
     173    /** 
     174     *  Not yet implemented (page 222 Rails books) 
     175     * 
     176     *  @var boolean 
     177     */     
     178    public $lock_optimistically = true; 
    160179 
    161180    # Table associations 
     
    271290     *  @var string[] 
    272291     */ 
    273     protected $aggregrations = array("count","sum","avg","max","min"); 
    274       
     292    protected $aggregations = array("count","sum","avg","max","min"); 
     293                
    275294    /** 
    276295     *  Primary key of the associated table 
     
    471490     *  Override call() to dynamically call the database associations 
    472491     *  @todo Document this API 
    473      *  @uses $aggregrations 
    474      *  @uses aggregrate_all() 
     492     *  @uses $aggregations 
     493     *  @uses aggregate_all() 
    475494     *  @uses get_association_type() 
    476495     *  @uses $belongs_to 
     
    482501     */ 
    483502    function __call($method_name, $parameters) { 
    484         if(method_exists($this,$method_name)) { 
     503        if(method_exists($this, $method_name)) { 
    485504            # If the method exists, just call it 
    486             $result = call_user_func(array($this,$method_name), $parameters); 
     505            $result = call_user_func_array(array($this, $method_name), $parameters); 
    487506        } else { 
    488507            # ... otherwise, check to see if the method call is one of our 
     
    490509            # ... first check for method names that match any of our explicitly 
    491510            # declared associations for this model ( e.g. $this->has_many = array("movies" => null) ) ... 
     511            if(is_array($parameters[0])) { 
     512                $parameters = $parameters[0];     
     513            } 
    492514            $association_type = $this->get_association_type($method_name); 
    493515            switch($association_type) { 
     
    507529 
    508530            # check for the [count,sum,avg,etc...]_all magic functions 
    509             if(substr($method_name, -4) == "_all" && in_array(substr($method_name, 0, -4),$this->aggregrations)) { 
     531            if(substr($method_name, -4) == "_all" && in_array(substr($method_name, 0, -4), $this->aggregations)) { 
    510532                //echo "calling method: $method_name<br>"; 
    511                 $result = $this->aggregrate_all($method_name, $parameters); 
     533                $result = $this->aggregate_all($method_name, $parameters); 
    512534            } 
    513535            # check for the find_all_by_* magic functions 
     
    527549        } 
    528550        return $result; 
    529     } 
    530  
    531     /** 
    532      *  Returns a the name of the join table that would be used for the two 
    533      *  tables.  The join table name is decided from the alphabetical order 
    534      *  of the two tables.  e.g. "genres_movies" because "g" comes before "m" 
    535      * 
    536      *  Parameters: $first_table, $second_table: the names of two database tables, 
    537      *   e.g. "movies" and "genres" 
    538      *  @todo Document this API 
    539      */ 
    540     private function get_join_table_name($first_table, $second_table) { 
    541         $tables = array(); 
    542         $tables["one"] = $first_table; 
    543         $tables["many"] = $second_table; 
    544         @asort($tables); 
    545         return @implode("_", $tables); 
    546551    } 
    547552 
     
    561566     */ 
    562567    private function find_all_habtm($other_table_name, $parameters = null) { 
    563          
     568        $additional_conditions = null; 
    564569        # Use any passed-in parameters 
    565         if (!is_null($parameters)) { 
     570        if(!is_null($parameters)) { 
    566571            if(@array_key_exists("conditions", $parameters)) { 
    567572                $additional_conditions = " AND (".$parameters['conditions'].")"; 
     
    630635             
    631636            # Primary key value 
    632             $this_primary_key_value = is_numeric($this->$this_primary_key) ? $this->$this_primary_key : "'".$this->$this_primary_key."'"; 
     637            $this_primary_key_value = $this->attribute_is_string($this_primary_key) ?  
     638                "'".$this->$this_primary_key."'" :  
     639                $this->$this_primary_key; 
    633640 
    634641            # Set up the SQL segments 
     
    652659        $additional_conditions = null; 
    653660        # Use any passed-in parameters 
    654         if (is_array($parameters)) { 
     661        if(is_array($parameters)) { 
    655662            if(@array_key_exists("conditions", $parameters)) { 
    656663                $additional_conditions = " AND (".$parameters['conditions'].")"; 
     
    705712             
    706713            $foreign_key_value = $this->$this_primary_key; 
    707             $conditions = (is_numeric($foreign_key_value) ?  
    708                 "$foreign_key = {$foreign_key_value}" :  
    709                 "$foreign_key = '{$foreign_key_value}'") . $additional_conditions;  
     714            $conditions = ($other_class_object->attribute_is_string($foreign_key) ?  
     715                "$foreign_key = '{$foreign_key_value}'" :  
     716                "$foreign_key = {$foreign_key_value}") . $additional_conditions;  
    710717        } 
    711718                          
     
    722729     *  @todo Document this API 
    723730     */ 
    724     private function find_one_has_one($other_object_name, $parameters = null) { 
    725          
     731    private function find_one_has_one($other_object_name, $parameters = null) {        
    726732        $additional_conditions = null; 
    727733        # Use any passed-in parameters 
    728         if (is_array($parameters)) { 
     734        if(is_array($parameters)) { 
    729735            //echo "<pre>";print_r($parameters); 
    730736            if(@array_key_exists("conditions", $parameters)) { 
     
    759765 
    760766        $foreign_key_value = $this->$this_primary_key; 
    761         $conditions = (is_numeric($foreign_key_value) ?  
    762             "{$foreign_key} = {$foreign_key_value}" :  
    763             "{$foreign_key} = '{$foreign_key_value}'") . $additional_conditions;  
     767        $conditions = ($other_class_object->attribute_is_string($foreign_key) ?  
     768            "{$foreign_key} = '{$foreign_key_value}'" :  
     769            "{$foreign_key} = {$foreign_key_value}") . $additional_conditions;  
    764770         
    765771        # Get the list of other_class_name objects 
    766772        $result = $other_class_object->find_first($conditions, $order); 
     773         
    767774        # There should only be one result, an object, if so return it 
    768         if(is_object($result)) { 
    769             return $result; 
    770         } else { 
    771             return null; 
    772         } 
     775        return (is_object($result) ? $result : null); 
    773776    } 
    774777 
     
    786789        $additional_conditions = null; 
    787790        # Use any passed-in parameters 
    788         if (is_array($parameters)) { 
     791        if(is_array($parameters)) { 
    789792            //echo "<pre>";print_r($parameters); 
    790793            if(@array_key_exists("conditions", $parameters)) { 
     
    819822         
    820823        $other_primary_key_value = $this->$foreign_key; 
    821         $conditions = (is_numeric($other_primary_key_value) ?  
    822             "{$other_primary_key} = {$other_primary_key_value}" :  
    823             "{$other_primary_key} = '{$other_primary_key_value}'") . $additional_conditions; 
     824        $conditions = ($other_class_object->attribute_is_string($other_primary_key) ?  
     825            "{$other_primary_key} = '{$other_primary_key_value}'" :  
     826            "{$other_primary_key} = {$other_primary_key_value}") . $additional_conditions; 
    824827         
    825828        # Get the list of other_class_name objects 
    826829        $result = $other_class_object->find_first($conditions, $order); 
     830         
    827831        # There should only be one result, an object, if so return it 
    828         if(is_object($result)) { 
    829             return $result; 
    830         } else { 
    831             return null; 
    832         } 
     832        return (is_object($result) ? $result : null); 
    833833    } 
    834834 
     
    842842     *  @param string $agrregrate_type SQL aggregate function to 
    843843     *    apply, suffixed '_all'.  The aggregate function is one of 
    844      *  the strings in {@link $aggregrations}.  
     844     *  the strings in {@link $aggregations}.  
    845845     *  @param string[] $parameters  Conditions to apply to the 
    846846     *    aggregate function.  If present, must be an array of three 
     
    857857     *  @uses is_error() 
    858858     */ 
    859     private function aggregrate_all($aggregrate_type, $parameters = null) { 
    860         $aggregrate_type = strtoupper(substr($aggregrate_type, 0, -4)); 
     859    private function aggregate_all($aggregate_type, $parameters = null) { 
     860        $aggregate_type = strtoupper(substr($aggregate_type, 0, -4)); 
    861861        ($parameters[0]) ? $field = $parameters[0] : $field = "*"; 
    862         $sql = "SELECT $aggregrate_type($field) AS agg_result FROM $this->table_name "; 
     862        $sql = "SELECT $aggregate_type($field) AS agg_result FROM $this->table_name "; 
    863863         
    864864        # Use any passed-in parameters 
    865         if (!is_null($parameters)) { 
     865        if(is_array($parameters[1])) { 
     866            extract($parameters[1]);    
     867        } elseif(!is_null($parameters)) { 
    866868            $conditions = $parameters[1]; 
    867             $joins = $parameters[2]; 
    868         } 
    869  
    870         if(!empty($joins)) $sql .= ",$joins "; 
    871         if(!empty($conditions)) $sql .= "WHERE $conditions "; 
    872  
    873         # echo "$aggregrate_type sql:$sql<br>"; 
     869            $order = $parameters[2]; 
     870            $joins = $parameters[3]; 
     871        } 
     872 
     873        if(!empty($joins)) $sql .= " $joins "; 
     874        if(!empty($conditions)) $sql .= " WHERE $conditions "; 
     875        if(!empty($order)) $sql .= " ORDER BY $order "; 
     876 
     877        # echo "$aggregate_type sql:$sql<br>"; 
    874878        if($this->is_error($rs = $this->query($sql))) { 
    875879            $this->raise($rs->getMessage()); 
     
    881885        } 
    882886        return 0; 
     887    } 
     888 
     889    /** 
     890     *  Returns a the name of the join table that would be used for the two 
     891     *  tables.  The join table name is decided from the alphabetical order 
     892     *  of the two tables.  e.g. "genres_movies" because "g" comes before "m" 
     893     * 
     894     *  Parameters: $first_table, $second_table: the names of two database tables, 
     895     *   e.g. "movies" and "genres" 
     896     *  @todo Document this API 
     897     */ 
     898    public function get_join_table_name($first_table, $second_table) { 
     899        $tables = array($first_table, $second_table); 
     900        @sort($tables); 
     901        return @implode("_", $tables); 
    883902    } 
    884903 
     
    10101029 
    10111030    /** 
    1012      *  Implement find_by_*() and find_all_by_* methods 
     1031     *  Implement find_by_*() and =_* methods 
    10131032     *   
    10141033     *  Converts a method name beginning 'find_by_' or 'find_all_by_' 
     
    10431062            $param_index = 0; 
    10441063            foreach($method_parts as $part) { 
    1045                 $value = is_numeric($parameters[$param_index]) ? $parameters[$param_index] : "'".$parameters[$param_index]."'"; 
    10461064                if($part == "AND") { 
    10471065                    $conditions .= " AND "; 
    10481066                    $param_index++; 
    10491067                } else { 
     1068                    $value = $this->attribute_is_string($part) ?  
     1069                        "'".$parameters[$param_index]."'" :  
     1070                        $parameters[$param_index];                     
    10501071                    $create_fields[$part] = $parameters[$param_index];   
    10511072                    $conditions .= "{$part} = {$value}"; 
     
    12821303                # passed in array of numbers array(1,2,4,23) 
    12831304                $primary_key = $this->primary_keys[0]; 
    1284                 $primary_key_values = is_numeric($id[0]) ? implode(",", $id) : "'".implode("','", $id)."'"; 
     1305                $primary_key_values = $this->attribute_is_string($primary_key) ?  
     1306                    "'".implode("','", $id)."'" :  
     1307                    implode(",", $id); 
    12851308                $options['conditions'] = "{$primary_key} IN({$primary_key_values})"; 
    12861309                $find_all = true; 
     
    12951318            # find an single record with id = $id 
    12961319            $primary_key = $this->primary_keys[0]; 
    1297             $primary_key_value = is_numeric($id) ? $id : "'".$id."'"; 
     1320            $primary_key_value = $this->attribute_is_string($primary_key) ? "'".$id."'" : $id ; 
    12981321            $options['conditions'] = "{$primary_key} = {$primary_key_value}"; 
    12991322        } 
     
    13891412     *        either create a row with all empty values, or it tries 
    13901413     *        to recurse once for each attribute in $attributes. 
    1391      *  FIXME: resolve calling sequence 
    13921414     *  Creates an object, instantly saves it as a record (if the validation permits it). 
    13931415     *  If the save fails under validations it returns false and $errors array gets set. 
    13941416     */ 
    13951417    function create($attributes, $dont_validate = false) { 
    1396         if(is_array($attributes)) { 
    1397             foreach($attributes as $attr) { 
    1398                 $this->create($attr, $dont_validate); 
    1399             } 
    1400         } else { 
    1401             $class_name = $this->get_class_name(); 
    1402             $object = new $class_name(); 
    1403             $object->save($attributes, $dont_validate); 
    1404         } 
     1418        $class_name = $this->get_class_name(); 
     1419        $object = new $class_name(); 
     1420        $result = $object->save($attributes, $dont_validate); 
     1421        return ($result ? $object : false); 
    14051422    } 
    14061423 
     
    14701487        //error_log("ActiveRecord::save() \$attributes=" 
    14711488        //          . var_export($attributes,true)); 
    1472         if(!is_null($attributes)) { 
     1489        if(is_array($attributes)) { 
    14731490            $this->update_attributes($attributes); 
    14741491        } 
     
    15221539     *  $content_columns} and the values from object variables. 
    15231540     *  Send the insert to the RDBMS. 
    1524      *  FIXME: Shouldn't we be saving the insert ID value as an object 
    1525      *  variable $this->id? 
    15261541     *  @uses $auto_save_habtm 
    15271542     *  @uses add_habtm_records() 
     
    15471562        //echo "add_record: SQL: $sql<br>"; 
    15481563        $result = $this->query($sql); 
    1549         if ($this->is_error($result)) { 
     1564        if($this->is_error($result)) { 
    15501565            $this->raise($results->getMessage()); 
    15511566        } else { 
     
    15541569            $primary_key_value = $this->get_insert_id(); 
    15551570             $this->$primary_key = $primary_key_value; 
    1556             if($primary_key_value > 0) { 
     1571            if($primary_key_value != '') { 
    15571572                if($this->auto_save_habtm) { 
    15581573                    $habtm_result = $this->add_habtm_records($primary_key_value); 
     
    16121627     *  returns the association type if defined in child class or null 
    16131628     *  @todo Document this API 
    1614      *  @todo <b>FIXME:</b> does the match algorithm match a substring 
    1615      *        of what we want to match? 
    16161629     *  @uses $belongs_to 
    16171630     *  @uses $has_and_belongs_to_many 
     
    17201733     */ 
    17211734    function delete($id = null) { 
    1722  
     1735        $deleted_ids = array(); 
    17231736        $primary_key_value = null; 
    17241737        $primary_key = $this->primary_keys[0]; 
     
    17261739            # Primary key's where clause from already loaded values 
    17271740            $conditions = $this->get_primary_key_conditions(); 
    1728             $primary_key_value = $this->$primary_key; 
    1729         } elseif(!is_array($id)) {  
    1730             $primary_key_value = $id;          
    1731             $id = is_numeric($id) ? $id : "'".$id."'"; 
    1732             $conditions = "{$primary_key} = $id"; 
     1741            $deleted_ids[] = $this->$primary_key; 
     1742        } elseif(!is_array($id)) {          
     1743            $deleted_ids[] = $id; 
     1744            $id = $this->attribute_is_string($primary_key) ? "'".$id."'" : $id; 
     1745            $conditions = "{$primary_key} = {$id}"; 
    17331746        } elseif(is_array($id)) { 
    1734             //$ids = ($this->attribute_is_string($primary_key)) ? "'".implode("','", $id)."'" : implode(',', $id); 
    1735             //$conditions = "{$primary_key} IN ($ids)"; 
     1747            $deleted_ids = $id; 
     1748            $ids = ($this->attribute_is_string($primary_key)) ?  
     1749                "'".implode("','", $id)."'" :  
     1750                implode(',', $id); 
     1751            $conditions = "{$primary_key} IN ({$ids})"; 
    17361752        } 
    17371753 
     
    17421758 
    17431759        $this->before_delete();  
    1744         $result = $this->delete_all($conditions); 
    1745         if($this->auto_delete_habtm && $primary_key_value != '') { 
    1746             if(is_string($this->has_and_belongs_to_many)) { 
    1747                 $habtms = explode(",", $this->has_and_belongs_to_many); 
    1748                 foreach($habtms as $other_table_name) { 
    1749                     $this->delete_all_habtm_records(trim($other_table_name), $primary_key_value);                              
     1760        if($result = $this->delete_all($conditions)) { 
     1761            foreach($deleted_ids as $id) { 
     1762                if($this->auto_delete_habtm && $id != '') { 
     1763                    if(is_string($this->has_and_belongs_to_many)) { 
     1764                        $habtms = explode(",", $this->has_and_belongs_to_many); 
     1765                        foreach($habtms as $other_table_name) { 
     1766                            $this->delete_all_habtm_records(trim($other_table_name), $id);                              
     1767                        } 
     1768                    } elseif(is_array($this->has_and_belongs_to_many)) { 
     1769                        foreach($this->has_and_belongs_to_many as $other_table_name => $values) { 
     1770                            $this->delete_all_habtm_records($other_table_name, $id);                              
     1771                        } 
     1772                    }  
    17501773                } 
    1751             } elseif(is_array($this->has_and_belongs_to_many)) { 
    1752                 foreach($this->has_and_belongs_to_many as $other_table_name => $values) { 
    1753                     $this->delete_all_habtm_records($other_table_name, $primary_key_value);                              
    1754                 } 
    1755             }  
    1756         } 
    1757         $this->after_delete(); 
    1758  
     1774            } 
     1775            $this->after_delete(); 
     1776        } 
     1777         
    17591778        return $result; 
    17601779    } 
     
    17871806            $this->raise($rs->getMessage()); 
    17881807        } 
    1789  
    1790         //  <b>FIXME: We don't know whether this row was deleted. 
    1791         //    What are the implications of making this a new record?</b> 
    1792         $this->id = 0; 
     1808         
    17931809        $this->new_record = true; 
    17941810        return true; 
     
    18821898            $habtm_table_name = $this->get_join_table_name($this->table_name,$other_table_name); 
    18831899            $this_foreign_key = Inflector::singularize($this->table_name)."_id"; 
    1884             $sql = "DELETE FROM $habtm_table_name WHERE $this_foreign_key = $this_foreign_value"; 
     1900            $sql = "DELETE FROM {$habtm_table_name} WHERE {$this_foreign_key} = {$this_foreign_value}"; 
    18851901            //echo "delete_all_habtm_records: SQL: $sql<br>"; 
    18861902            $result = $this->query($sql); 
     
    19521968        //error_log('update_attributes()'); 
    19531969 
    1954         //  Test each attribute to be updated 
    1955         //  and process according to its type 
    1956         foreach($attributes as $field => $value) { 
    1957             # datetime / date parts check 
    1958             if(preg_match('/^\w+\(.*i\)$/i', $field)) { 
    1959  
    1960                 //  The name of this attribute ends in "(?i)" 
    1961                 //  indicating that it's part of a date or time 
    1962  
    1963                 //  Accumulate all the pieces of a date and time in 
    1964                 //  array $datetime_key.  The keys in the array are 
    1965                 //  the names of date/time attributes with the final 
    1966                 //  "(?i)" stripped off. 
    1967                 $datetime_key = substr($field, 0, strpos($field, "(")); 
    1968                 if( !isset($old_datetime_key) 
    1969                     || ($datetime_key != $old_datetime_key)) { 
    1970  
    1971                     //  This value of $datetime_key hasn't been seen 
    1972                     //  before, so remember it. 
    1973                     $old_datetime_key = $datetime_key;                      
    1974  
    1975                     //  $datetime_value accumulates the pieces of the 
    1976                     //  date/time attribute $datetime_key 
    1977                     $datetime_value = "";    
    1978                 }  
    1979  
    1980                 //  Concatentate pieces of the attribute's value 
    1981                 //  FIXME: this only works if the array elements 
    1982                 //  are sorted by key.  Is this guaranteed? 
    1983                 if(strstr($field, "2i") || strstr($field, "3i")) { 
    1984                     $datetime_value .= "-".$value;     
    1985                 } elseif(strstr($field, "4i")) { 
    1986                     $datetime_value .= " ".$value;         
    1987                 } elseif(strstr($field, "5i")) { 
    1988                     $datetime_value .= ":".$value;         
     1970        if(is_array($attributes)) { 
     1971            //  Test each attribute to be updated 
     1972            //  and process according to its type 
     1973            foreach($attributes as $field => $value) { 
     1974                # datetime / date parts check 
     1975                if(preg_match('/^\w+\(.*i\)$/i', $field)) { 
     1976     
     1977                    //  The name of this attribute ends in "(?i)" 
     1978                    //  indicating that it's part of a date or time 
     1979     
     1980                    //  Accumulate all the pieces of a date and time in 
     1981                    //  array $datetime_key.  The keys in the array are 
     1982                    //  the names of date/time attributes with the final 
     1983                    //  "(?i)" stripped off. 
     1984                    $datetime_key = substr($field, 0, strpos($field, "(")); 
     1985                    if( !isset($old_datetime_key) 
     1986                        || ($datetime_key != $old_datetime_key)) { 
     1987     
     1988                        //  This value of $datetime_key hasn't been seen 
     1989                        //  before, so remember it. 
     1990                        $old_datetime_key = $datetime_key;                      
     1991     
     1992                        //  $datetime_value accumulates the pieces of the 
     1993                        //  date/time attribute $datetime_key 
     1994                        $datetime_value = "";    
     1995                    }  
     1996     
     1997                    //  Concatentate pieces of the attribute's value 
     1998                    //  FIXME: this only works if the array elements 
     1999                    //  are sorted by key.  Is this guaranteed? 
     2000                    if(strstr($field, "2i") || strstr($field, "3i")) { 
     2001                        $datetime_value .= "-".$value;     
     2002                    } elseif(strstr($field, "4i")) { 
     2003                        $datetime_value .= " ".$value;         
     2004                    } elseif(strstr($field, "5i")) { 
     2005                        $datetime_value .= ":".$value;         
     2006                    } else { 
     2007                        $datetime_value .= $value;     
     2008                    }   
     2009                    $datetime_fields[$old_datetime_key] = $datetime_value;      
     2010                    # this elseif checks if first its an object if its parent is ActiveRecord             
     2011                } elseif(is_object($value) && get_parent_class($value) == __CLASS__ && $this->auto_save_associations) { 
     2012                    if($association_type = $this->get_association_type($field)) { 
     2013                        $this->save_associations[$association_type][] = $value; 
     2014                        if($association_type == "belongs_to") { 
     2015                            $primary_key = $value->primary_keys[0]; 
     2016                            $foreign_key = Inflector::singularize($value->table_name)."_".$primary_key; 
     2017                            $this->$foreign_key = $value->$primary_key;  
     2018                        } 
     2019                    } 
     2020                    # this elseif checks if its an array of objects and if its parent is ActiveRecord                 
     2021                } elseif(is_array($value) && $this->auto_save_associations) { 
     2022                    if($association_type = $this->get_association_type($field)) { 
     2023                        $this->save_associations[$association_type][] = $value; 
     2024                    } 
    19892025                } else { 
    1990                     $datetime_value .= $value;     
    1991                 }   
    1992                 $datetime_fields[$old_datetime_key] = $datetime_value;      
    1993                 # this elseif checks if first its an object if its parent is ActiveRecord             
    1994             } elseif(is_object($value) && get_parent_class($value) == __CLASS__ && $this->auto_save_associations) { 
    1995                 if($association_type = $this->get_association_type($field)) { 
    1996                     $this->save_associations[$association_type][] = $value; 
    1997                     if($association_type == "belongs_to") { 
    1998                         $primary_key = $value->primary_keys[0]; 
    1999                         $foreign_key = Inflector::singularize($value->table_name)."_".$primary_key; 
    2000                         $this->$foreign_key = $value->$primary_key;  
    2001                     } 
     2026     
     2027                    //  Just a simple attribute, copy it 
     2028                    $this->$field = $value; 
    20022029                } 
    2003                 # this elseif checks if its an array of objects and if its parent is ActiveRecord                 
    2004             } elseif(is_array($value) && $this->auto_save_associations) { 
    2005                 if($association_type = $this->get_association_type($field)) { 
    2006                     $this->save_associations[$association_type][] = $value; 
    2007                 } 
    2008             } else { 
    2009  
    2010                 //  Just a simple attribute, copy it 
    2011                 $this->$field = $value; 
    2012             } 
    2013         } 
    2014  
    2015         //  If any date/time fields were found, assign the 
    2016         //  accumulated values to corresponding attributes 
    2017         if(isset($datetime_fields) 
    2018            && is_array($datetime_fields)) { 
    2019             foreach($datetime_fields as $field => $value) { 
    2020                 //error_log("$field = $value"); 
    2021                 $this->$field = $value;     
    2022             }     
    2023         } 
    2024         $this->set_habtm_attributes($attributes); 
     2030            } 
     2031     
     2032            //  If any date/time fields were found, assign the 
     2033            //  accumulated values to corresponding attributes 
     2034            if(isset($datetime_fields) 
     2035               && is_array($datetime_fields)) { 
     2036                foreach($datetime_fields as $field => $value) { 
     2037                    //error_log("$field = $value"); 
     2038                    $this->$field = $value;     
     2039                }     
     2040            } 
     2041            $this->set_habtm_attributes($attributes); 
     2042        } 
    20252043    } 
    20262044 
     
    20762094            if(!(preg_match('/^\w+\(.*\)$/U', $value))  
    20772095               && !(strcasecmp($value, 'NULL') == 0)  
    2078                && !is_numeric($value)) { 
    2079                 $value = str_replace("\\\"","\"",$value); 
    2080                 $value = str_replace("\'","'",$value); 
    2081                 $value = str_replace("\\\\","\\",$value); 
     2096               && $this->attribute_is_string($key)) { 
     2097                $value = str_replace("\\\"","\"", $value); 
     2098                $value = str_replace("\'","'", $value); 
     2099                $value = str_replace("\\\\","\\", $value); 
    20822100                $return[$key] = "'" . addslashes($value) . "'"; 
    20832101            } else { 
     
    21582176            # run through our fields and join them with their values 
    21592177            foreach($attributes as $key => $value) { 
    2160                 if($key && ($value || is_numeric($value)) && !in_array($key, $this->primary_keys)) { 
     2178                if($key && isset($value) && !in_array($key, $this->primary_keys)) { 
    21612179                    $updates[] = "$key = $value"; 
    21622180                } 
     
    22042222     *  store it in {@link $content_columns}.  Add a more human 
    22052223     *  friendly name to the element for each column. 
    2206      *  <b>FIXME: should throw an exception if tableInfo() fails</b> 
    22072224     *  @uses $db 
    22082225     *  @uses $content_columns 
     
    22132230    function set_content_columns($table_name) { 
    22142231        $this->content_columns = self::$db->tableInfo($table_name); 
     2232        if($this->is_error($this->content_columns)) { 
     2233            $this->raise($this->content_columns->getMessage());         
     2234        } 
    22152235        if(is_array($this->content_columns)) { 
    22162236            $i = 0; 
     
    23762396    function get_errors_as_string($seperator = "<br>") { 
    23772397        return $this->get_errors(true, $seperator); 
     2398    } 
     2399 
     2400    /** 
     2401     *  Determine if passed in attribute (table column) is a string 
     2402     *  @param string $attribute Name of the table column 
     2403     *  @uses column_for_attribute() 
     2404     */     
     2405    function attribute_is_string($attribute) { 
     2406        $column = $this->column_for_attribute($attribute); 
     2407        switch($column['type']) { 
     2408            case 'string': 
     2409            case 'varchar': 
     2410            case 'varchar2': 
     2411            case 'text': 
     2412            case 'blob': 
     2413            case 'date': 
     2414            case 'datetime': 
     2415            case 'timestamp': 
     2416                return true; 
     2417        } 
     2418        return false;         
    23782419    } 
    23792420