Changeset 308 for trunk/trax/vendor/trax/active_record.php
- Timestamp:
- 03/19/09 10:40:34 (3 years ago)
- Files:
-
- 1 modified
-
trunk/trax/vendor/trax/active_record.php (modified) (64 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/trax/vendor/trax/active_record.php
r307 r308 147 147 148 148 /** 149 * Index into the $ active_connectionsarray149 * Index into the $connection_pool array 150 150 * 151 151 * Name of the index to use to return or set the current db connection … … 156 156 public $connection_name = null; 157 157 158 /** 159 * Index into the $connection_pool_read_only array 160 * 161 * Name of the index to use to return or set the current db connection 162 * Mainly used if you want to force all reads(SELECT's) to goto a 163 * specific database server. 164 * @var string 165 */ 166 public $read_only_connection_name = null; 167 168 /** 169 * Index into the $connection_pool_read_only array 170 * 171 * Same as $read_only_connection_name but set for all models globally. 172 * @var string 173 */ 174 public static $global_read_only_connection_name = null; 175 158 176 /** 159 177 * What environment to run in. … … 167 185 168 186 /** 169 * Stores the active connections. Indexed on $connection_name.187 * Stores the active read/write connections. Indexed on $connection_name. 170 188 */ 171 public static $active_connections = array(); 189 public static $connection_pool = array(); 190 191 /** 192 * Stores the active read only connections. Indexed on $connection_name. 193 */ 194 public static $connection_pool_read_only = array(); 172 195 173 196 /** … … 344 367 * @var integer 345 368 */ 346 public $rows_per_page_default = 20;369 public static $rows_per_page_default = 20; 347 370 348 371 /** … … 355 378 */ 356 379 public $pagination_count = 0; 380 381 /** 382 * @todo Document this variable 383 */ 384 public $page = 0; 385 386 /** 387 * Sets the default options for the model. 388 * 389 * class Person extends ActiveRecord { 390 * public $default_scope = array( 391 * 'order' => 'last_name, first_name' 392 * )); 393 * } 394 * 395 */ 396 public $default_scope = array(); 397 398 /** 399 * Adds a class method for retrieving and querying objects. 400 * A scope represents a narrowing of a database query, such as 401 * 'conditions' => "first_name = 'John'" 402 * 403 * class Person extends ActiveRecord { 404 * public $named_scope = array( 405 * 'people_named_john' => array( 406 * 'conditions' => "first_name = 'John'", 407 * 'order' => 'last_name, first_name' 408 * )); 409 * } 410 * 411 * $person = new Person; 412 * $person->people_named_john; # an array of AR objects people first_name = 'John' 413 * 414 */ 415 public $named_scope = array(); 416 357 417 358 418 /** … … 430 490 * This is for transactions only to let query() know that a 'BEGIN' has been executed 431 491 */ 432 private static $ begin_executed= false;492 private static $in_transaction = false; 433 493 434 494 /** … … 436 496 * This will issue a rollback command if any sql fails. 437 497 */ 438 public static $ use_transactions= false;498 public static $auto_rollback = false; 439 499 440 500 /** … … 460 520 */ 461 521 function __construct($attributes = null) { 462 # Open the database connection 463 $this->establish_connection(); 522 # Open the database connection for reads / writes 523 self::$db = $this->establish_connection(); 524 if($this->read_only_connection_name) { 525 # Open database connection for all reads 526 $this->establish_connection($this->read_only_connection_name, true); 527 } elseif(self::$global_read_only_connection_name) { 528 # Open database connection for all reads 529 $this->establish_connection(self::$global_read_only_connection_name, true); 530 } 464 531 465 532 # Set $table_name … … 522 589 break; 523 590 } 591 } elseif(array_key_exists($key, $this->named_scope) && is_array($this->named_scope[$key])) { 592 $this->$key = $this->find_all($this->named_scope[$key]); 524 593 } elseif($this->is_composite($key)) { 525 594 $composite_object = $this->get_composite_object($key); … … 598 667 switch($association_type) { 599 668 case "has_many": 669 $parameters = is_array($this->has_many) && @array_key_exists($method_name, $this->has_many) ? 670 array_merge($this->has_many[$method_name], $parameters) : $parameters; 600 671 $result = $this->find_all_has_many($method_name, $parameters); 601 672 break; 602 673 case "has_one": 674 $parameters = is_array($this->has_one) && @array_key_exists($method_name, $this->has_one) ? 675 array_merge($this->has_one[$method_name], $parameters) : $parameters; 603 676 $result = $this->find_one_has_one($method_name, $parameters); 604 677 break; 605 678 case "belongs_to": 679 $parameters = is_array($this->belongs_to) && @array_key_exists($method_name, $this->belongs_to) ? 680 array_merge($this->belongs_to[$method_name], $parameters) : $parameters; 606 681 $result = $this->find_one_belongs_to($method_name, $parameters); 607 682 break; 608 683 case "has_and_belongs_to_many": 684 $parameters = is_array($this->has_and_belongs_to_many) && @array_key_exists($method_name, $this->has_and_belongs_to_many) ? 685 array_merge($this->has_and_belongs_to_many[$method_name], $parameters) : $parameters; 609 686 $result = $this->find_all_habtm($method_name, $parameters); 610 687 break; … … 649 726 */ 650 727 private function find_all_habtm($other_table_name, $parameters = null) { 651 $additional_conditions = null; 728 $additional_conditions = $additional_joins = null; 729 $options = array(); 652 730 # Use any passed-in parameters 653 if(!is_null($parameters)) { 731 if(!is_null($parameters)) { 654 732 if(@array_key_exists("conditions", $parameters)) { 655 733 $additional_conditions = " AND (".$parameters['conditions'].")"; … … 658 736 } 659 737 if(@array_key_exists("order", $parameters)) { 660 $o rder= $parameters['order'];738 $options['order'] = $parameters['order']; 661 739 } elseif($parameters[1] != "") { 662 $o rder= $parameters[1];740 $options['order'] = $parameters[1]; 663 741 } 664 742 if(@array_key_exists("limit", $parameters)) { 665 $ limit= $parameters['limit'];743 $options['limit'] = $parameters['limit']; 666 744 } elseif($parameters[2] != "") { 667 $limit = $parameters[2]; 668 } 745 $options['limit'] = $parameters[2]; 746 } 747 if(@array_key_exists("joins", $parameters)) { 748 $additional_joins = $parameters['joins']; 749 } elseif($parameters[3] != "") { 750 $additional_joins = $parameters[3]; 751 } 752 if(@array_key_exists("page", $parameters)) { 753 $options['page'] = $parameters['page']; 754 } 755 if(@array_key_exists("per_page", $parameters)) { 756 $options['per_page'] = $parameters['per_page']; 757 } 669 758 if(@array_key_exists("class_name", $parameters)) { 670 759 $other_object_name = $parameters['class_name']; … … 697 786 if(!is_null($finder_sql)) { 698 787 $conditions = $finder_sql; 699 $order = null;700 $limit = null;701 $joins = null;702 788 } else { 703 789 # Prepare the join table name primary keys (fields) to do the join on … … 729 815 } 730 816 817 if($this->habtm_sort_field) { 818 $options['order'] = (isset($options['order']) ? $options['order'].',':'')."{$join_table}.{$this->habtm_sort_field}"; 819 } 820 731 821 # Set up the SQL segments 732 822 $conditions = "{$join_table}.{$this_foreign_key} = {$this_primary_key_value}".$additional_conditions; 733 $joins = "LEFT JOIN {$join_table} ON {$other_table_name}.{$other_primary_key} = {$join_table}.{$other_foreign_key}"; 734 } 823 $options['joins'] = "LEFT JOIN {$join_table} ON {$other_table_name}.{$other_primary_key} = {$join_table}.{$other_foreign_key}".$additional_joins; 824 } 825 $options['conditions'] = $conditions; 735 826 736 827 # Get the list of other_class_name objects 737 return $other_class_object->find_all($ conditions, $order, $limit, $joins);828 return $other_class_object->find_all($options); 738 829 } 739 830 … … 747 838 */ 748 839 private function find_all_has_many($other_table_name, $parameters = null) { 749 $additional_conditions= null;840 $additional_conditions = $order = $limit = null; 750 841 # Use any passed-in parameters 751 842 if(is_array($parameters)) { … … 756 847 } 757 848 if(@array_key_exists("order", $parameters)) { 758 $o rder= $parameters['order'];849 $options['order'] = $parameters['order']; 759 850 } elseif($parameters[1] != "") { 760 $o rder= $parameters[1];851 $options['order'] = $parameters[1]; 761 852 } 762 853 if(@array_key_exists("limit", $parameters)) { 763 $ limit= $parameters['limit'];854 $options['limit'] = $parameters['limit']; 764 855 } elseif($parameters[2] != "") { 765 $limit = $parameters[2]; 766 } 856 $options['limit'] = $parameters[2]; 857 } 858 if(@array_key_exists("joins", $parameters)) { 859 $options['joins'] = $parameters['joins']; 860 } elseif($parameters[3] != "") { 861 $options['joins'] = $parameters[3]; 862 } 863 if(@array_key_exists("page", $parameters)) { 864 $options['page'] = $parameters['page']; 865 } 866 if(@array_key_exists("per_page", $parameters)) { 867 $options['per_page'] = $parameters['per_page']; 868 } 767 869 if(@array_key_exists("foreign_key", $parameters)) { 768 870 $foreign_key = $parameters['foreign_key']; … … 773 875 if(@array_key_exists("finder_sql", $parameters)) { 774 876 $finder_sql = $parameters['finder_sql']; 775 } 877 } 776 878 } 777 879 … … 788 890 if(!is_null($finder_sql)) { 789 891 $conditions = $finder_sql; 790 $order = null;791 $limit = null;792 $joins = null;793 892 } else { 794 893 # This class primary key … … 813 912 $conditions .= $additional_conditions; 814 913 } 815 914 $options['conditions'] = $conditions; 915 #error_log("has_many:".print_r($options, true)); 816 916 # Get the list of other_class_name objects 817 return $other_class_object->find_all($ conditions, $order, $limit, $joins);917 return $other_class_object->find_all($options); 818 918 } 819 919 … … 857 957 $this_primary_key = $this->primary_keys[0]; 858 958 859 if(!$foreign_key) {959 if(!$foreign_key) { 860 960 $foreign_key = Inflector::singularize($this->table_name)."_".$this_primary_key; 861 961 } … … 979 1079 980 1080 # echo "$aggregate_type sql:$sql<br>"; 981 if($this->is_error($rs = $this->query($sql))) { 1081 //print_r($parameters[0]); 1082 //echo $sql; 1083 if($this->is_error($rs = $this->query($sql, true))) { 982 1084 $this->raise($rs->getMessage()); 983 1085 } else { … … 1078 1180 if($this->column_attribute_exists($column) && ($conditions = $this->get_primary_key_conditions())) { 1079 1181 # Run the query to grab a specific columns value. 1080 $sql = "SELECT {$column} FROM {$this->table_prefix}{$this->table_name} WHERE {$conditions} ";1182 $sql = "SELECT {$column} FROM {$this->table_prefix}{$this->table_name} WHERE {$conditions} LIMIT 1"; 1081 1183 $this->log_query($sql); 1082 $result = self::$db->queryOne($sql); 1184 $db = $this->get_connection(true); 1185 $result = $db->queryOne($sql); 1083 1186 if($this->is_error($result)) { 1084 1187 $this->raise($result->getMessage()); … … 1094 1197 * @todo Document this API 1095 1198 */ 1096 function begin() { 1097 self::$db->query("BEGIN"); 1098 $this->begin_executed = true; 1199 function begin($save_point = null) { 1200 # check if transaction are supported by this driver 1201 if(self::$db->supports('transactions')) { 1202 $rs = self::$db->beginTransaction(); 1203 if($this->is_error($rs)) { 1204 $this->raise($rs->getMessage()); 1205 } 1206 self::$in_transaction = true; 1207 } 1208 } 1209 1210 /** 1211 * Only used if you want to do transactions and your db supports transactions 1212 * 1213 * @uses $db 1214 * @todo Document this API 1215 */ 1216 function save_point($save_point) { 1217 if(!is_null($save_point)) { 1218 # check if transaction are supported by this driver 1219 if(self::$db->supports('transactions')) { 1220 # check if we are inside a transaction and if savepoints are supported 1221 if(self::$db->inTransaction() && self::$db->supports('savepoints')) { 1222 # Set a savepoint 1223 $rs = self::$db->beginTransaction($save_point); 1224 if($this->is_error($rs)) { 1225 $this->raise($rs->getMessage()); 1226 } 1227 } 1228 } 1229 } 1099 1230 } 1100 1231 … … 1105 1236 * @todo Document this API 1106 1237 */ 1107 function commit() { 1108 self::$db->query("COMMIT"); 1109 $this->begin_executed = false; 1238 function commit() { 1239 # check if transaction are supported by this driver 1240 if(self::$db->supports('transactions')) { 1241 # check if we are inside a transaction 1242 if(self::$db->inTransaction()) { 1243 $rs = self::$db->commit(); 1244 if($this->is_error($rs)) { 1245 $this->raise($rs->getMessage()); 1246 } 1247 self::$in_transaction = false; 1248 } 1249 } 1110 1250 } 1111 1251 … … 1115 1255 * @uses $db 1116 1256 * @todo Document this API 1117 */ 1257 */ 1118 1258 function rollback() { 1119 self::$db->query("ROLLBACK"); 1259 # check if transaction are supported by this driver 1260 if(self::$db->supports('transactions')) { 1261 $rs = self::$db->rollback(); 1262 if($this->is_error($rs)) { 1263 $this->raise($rs->getMessage()); 1264 } 1265 self::$in_transaction = false; 1266 } 1120 1267 } 1121 1268 … … 1131 1278 * @throws {@link ActiveRecordError} 1132 1279 */ 1133 function query($sql ) {1280 function query($sql, $read_only = false) { 1134 1281 # Run the query 1135 1282 $this->log_query($sql); 1136 $rs =& self::$db->query($sql); 1283 $db = $this->get_connection($read_only); 1284 $rs =& $db->query($sql); 1137 1285 if ($this->is_error($rs)) { 1138 if(self::$ use_transactions && self::$begin_executed) {1286 if(self::$auto_rollback && self::$in_transaction) { 1139 1287 $this->rollback(); 1140 1288 } … … 1241 1389 1242 1390 $offset = null; 1391 $page = null; 1243 1392 $per_page = null; 1244 1393 $select = null; 1394 $paginate = false; 1245 1395 1246 1396 # this is if they passed in an associative array to emulate … … 1280 1430 # If conditions specified, include them 1281 1431 if(!is_null($conditions)) { 1432 if(array_key_exists('conditions', $this->default_scope) 1433 && !is_null($this->default_scope['conditions'])) { 1434 $conditions = " ({$conditions}) AND (".$this->default_scope['conditions'].") "; 1435 } 1282 1436 $sql .= "WHERE $conditions "; 1437 } elseif(array_key_exists('conditions', $this->default_scope) 1438 && !is_null($this->default_scope['conditions'])) { 1439 $sql .= "WHERE ".$this->default_scope['conditions']." "; 1283 1440 } 1284 1441 1285 1442 # If ordering specified, include it 1286 1443 if(!is_null($order)) { 1444 if(array_key_exists('order', $this->default_scope) 1445 && !is_null($this->default_scope['order'])) { 1446 $order = " {$order},".$this->default_scope['order']." "; 1447 } 1287 1448 $sql .= "ORDER BY $order "; 1449 } elseif(array_key_exists('order', $this->default_scope) 1450 && !is_null($this->default_scope['order'])) { 1451 $sql .= "ORDER BY ".$this->default_scope['order']." "; 1288 1452 } 1289 1453 1290 1454 # Is output to be generated in pages? 1291 if(is_numeric($limit) || is_numeric($offset) || is_numeric($per_page)) { 1455 if(is_numeric($limit) || is_numeric($offset) || is_numeric($per_page) || is_numeric($page)) { 1456 #error_log("limit:$limit offset:$offset per_page:$per_page page:$page"); 1292 1457 1293 1458 if(is_numeric($limit)) { 1294 $this->rows_per_page = $limit;1459 $this->rows_per_page = (int)$limit; 1295 1460 } 1296 1461 if(is_numeric($per_page)) { 1297 $this->rows_per_page = $per_page; 1462 $this->rows_per_page = (int)$per_page; 1463 $paginate = true; 1298 1464 } 1299 1465 # Default for rows_per_page: 1300 1466 if ($this->rows_per_page <= 0) { 1301 $this->rows_per_page = $this->rows_per_page_default;1467 $this->rows_per_page = (int)self::$rows_per_page_default; 1302 1468 } 1303 1469 1304 1470 # Only use request's page if you are calling from find_all_with_pagination() and if it is int 1305 if(strval(intval($_REQUEST['page'])) == $_REQUEST['page']) { 1306 $this->page = $_REQUEST['page']; 1471 #if(isset($_REQUEST['page']) && strval(intval($_REQUEST['page'])) == $_REQUEST['page']) { 1472 #$this->page = $_REQUEST['page']; 1473 #} 1474 if(!is_null($page)) { 1475 $this->page = (int)$page; 1476 $paginate = true; 1307 1477 } 1308 1478 … … 1319 1489 # $sql .= "LIMIT $offset, $this->rows_per_page"; 1320 1490 1321 # Set number of total pages in result set 1322 if($count = $this->count_all($this->primary_keys[0], $conditions, $joins)) { 1323 $this->pagination_count = $count; 1324 $this->pages = (($count % $this->rows_per_page) == 0) 1325 ? $count / $this->rows_per_page 1326 : floor($count / $this->rows_per_page) + 1; 1491 if($paginate) { 1492 #error_log("I am going to paginate."); 1493 # Set number of total pages in result set 1494 if($count = $this->count_all($this->primary_keys[0], $conditions, $joins)) { 1495 $this->pagination_count = $count; 1496 $this->pages = (($count % $this->rows_per_page) == 0) 1497 ? $count / $this->rows_per_page 1498 : floor($count / $this->rows_per_page) + 1; 1499 } 1327 1500 } 1328 1501 } … … 1331 1504 return $sql; 1332 1505 } 1506 1507 /** 1508 * Returns same as find_all 1509 * 1510 */ 1511 function paginate($page = 1, $per_page = 0, $options = array()) { 1512 if(is_array($page)) { 1513 $options = $page; 1514 } else { 1515 $options['page'] = (int)($page > 0 ? $page : 1); 1516 $options['per_page'] = (int)($per_page > 0 ? $per_page : self::$rows_per_page_default); 1517 } 1518 $options['paginate'] = true; 1519 return $this->find_all($options); 1520 } 1333 1521 1334 1522 /** … … 1372 1560 # echo "query: $sql\n"; 1373 1561 # error_log("ActiveRecord::find_all -> $sql"); 1374 if($this->is_error($rs = $this->query($sql ))) {1562 if($this->is_error($rs = $this->query($sql, true))) { 1375 1563 $this->raise($rs->getMessage()); 1376 1564 } 1377 1565 1378 1566 $objects = array(); 1379 while($row = $rs->fetchRow()) { 1380 $class_name = $this->get_class_name();1567 $class_name = $this->get_class_name(); 1568 while($row = $rs->fetchRow()) { 1381 1569 $object = new $class_name(); 1382 1570 $object->new_record = false; … … 1386 1574 if($field == $this->index_on) { 1387 1575 $objects_key = $value; 1388 } 1389 } 1390 if(is_null($objects_key)) {1391 $objects[] = $object;1576 } 1577 } 1578 if(is_null($objects_key)) { 1579 $objects[] = $object; 1392 1580 } else { 1393 $objects[$objects_key] = $object; 1581 $objects[$objects_key] = $object; 1394 1582 } 1395 1583 # If callback is defined in model run it. … … 1711 1899 1712 1900 if($this->is_error($result)) { 1713 $this->raise($result s->getMessage());1901 $this->raise($result->getMessage()); 1714 1902 } else { 1715 1903 $habtm_result = true; … … 1762 1950 $result = $this->query($sql); 1763 1951 if($this->is_error($result)) { 1764 $this->raise($result s->getMessage());1952 $this->raise($result->getMessage()); 1765 1953 } else { 1766 1954 $habtm_result = true; … … 1946 2134 1947 2135 if(is_null($conditions)) { 1948 $this-> errors[] = "No conditions specified to delete on.";2136 $this->add_error("No conditions specified to delete on."); 1949 2137 return false; 1950 2138 } 1951 2139 1952 $this->before_delete(); 1953 if($result = $this->delete_all($conditions)) { 1954 foreach($deleted_ids as $id) { 1955 if($this->auto_delete_habtm && $id != '') { 1956 if(is_string($this->has_and_belongs_to_many)) { 1957 $habtms = explode(",", $this->has_and_belongs_to_many); 1958 foreach($habtms as $other_table_name) { 1959 $this->delete_all_habtm_records(trim($other_table_name), $id); 1960 } 1961 } elseif(is_array($this->has_and_belongs_to_many)) { 1962 foreach($this->has_and_belongs_to_many as $other_table_name => $values) { 1963 $this->delete_all_habtm_records($other_table_name, $id); 1964 } 1965 } 2140 if($this->before_delete()) { 2141 if($result = $this->delete_all($conditions)) { 2142 foreach($deleted_ids as $id) { 2143 if($this->auto_delete_habtm && $id != '') { 2144 if(is_string($this->has_and_belongs_to_many)) { 2145 $habtms = explode(",", $this->has_and_belongs_to_many); 2146 foreach($habtms as $other_table_name) { 2147 $this->delete_all_habtm_records(trim($other_table_name), $id); 2148 } 2149 } elseif(is_array($this->has_and_belongs_to_many)) { 2150 foreach($this->has_and_belongs_to_many as $other_table_name => $values) { 2151 $this->delete_all_habtm_records($other_table_name, $id); 2152 } 2153 } 2154 } 1966 2155 } 1967 } 1968 $this->after_delete(); 1969 } 1970 2156 $this->after_delete(); 2157 } 2158 } 1971 2159 return $result; 1972 2160 } … … 1991 2179 function delete_all($conditions = null) { 1992 2180 if(is_null($conditions)) { 1993 $this-> errors[] = "No conditions specified to delete on.";2181 $this->add_error("No conditions specified to delete on."); 1994 2182 return false; 1995 2183 } … … 2046 2234 if($this->delete_habtm_records($this_foreign_value)) { 2047 2235 reset($this->habtm_attributes); 2236 if($this->habtm_sort_field) { 2237 $sort_field = $this->habtm_sort_field; 2238 $sort_value = 0; 2239 } 2048 2240 foreach($this->habtm_attributes as $other_table_name => $other_foreign_values) { 2049 2241 $table_name = $this->get_join_table_name($this->table_name,$other_table_name); … … 2054 2246 $attributes[$this_foreign_key] = $this_foreign_value; 2055 2247 $attributes[$other_foreign_key] = $other_foreign_value; 2248 if($sort_field) { 2249 $attributes[$sort_field] = $sort_value; 2250 $sort_value++; 2251 } 2056 2252 $attributes = $this->quoted_attributes($attributes); 2057 2253 $fields = @implode(', ', array_keys($attributes)); 2058 2254 $values = @implode(', ', array_values($attributes)); 2059 2255 $sql = "INSERT INTO $table_name ($fields) VALUES ($values)"; 2060 //echo "add_habtm_records: SQL: $sql<br>";2256 error_log("add_habtm_records: SQL: $sql"); 2061 2257 $result = $this->query($sql); 2062 2258 if ($this->is_error($result)) { … … 2193 2389 } 2194 2390 } 2195 2391 2196 2392 // If any date/time fields were found, assign the 2197 2393 // accumulated values to corresponding attributes 2394 // 1i = Year, 2i = Month, 3i = Day, 4i = Hour, 5i = Minute 2198 2395 if(count($datetime_fields)) { 2199 2396 foreach($datetime_fields as $datetime_field) { 2200 2397 $datetime_format = ''; 2201 2398 $datetime_value = ''; 2399 # Date Year / Month / Day 2202 2400 if($attributes[$datetime_field."(1i)"] 2203 2401 && $attributes[$datetime_field."(2i)"] … … 2207 2405 . "-" . $attributes[$datetime_field."(3i)"]; 2208 2406 $datetime_format = $this->date_format; 2209 } 2407 } 2408 # for expiration dates Year & Month 2409 elseif($attributes[$datetime_field."(1i)"] 2410 && $attributes[$datetime_field."(2i)"]) { 2411 $datetime_value = $attributes[$datetime_field."(1i)"] 2412 . "-" . $attributes[$datetime_field."(2i)"]; 2413 $datetime_format = $this->date_format; 2414 } 2210 2415 $datetime_value .= " "; 2416 # Time Hour & Minutes 2211 2417 if($attributes[$datetime_field."(4i)"] 2212 2418 && $attributes[$datetime_field."(5i)"]) { … … 2405 2611 } 2406 2612 2613 function human_attribute_name($attribute) { 2614 return Inflector::humanize($attribute); 2615 } 2616 2407 2617 /** 2408 2618 * Set {@link $table_name} from the class name of this object … … 2439 2649 * @uses $db 2440 2650 * @uses $content_columns 2441 * @uses Inflector::humanize()2651 * @uses human_attribute_name() 2442 2652 * @see __set() 2443 2653 * @param string $table_name Name of table to get information about … … 2458 2668 $i = 0; 2459 2669 foreach($this->content_columns as $column) { 2460 $this->content_columns[$i++]['human_name'] = Inflector::humanize($column['name']);2670 $this->content_columns[$i++]['human_name'] = $this->human_attribute_name($column['name']); 2461 2671 } 2462 2672 self::$table_info[$table_name] = $this->content_columns; … … 2496 2706 * 2497 2707 * If there is a connection now open, as indicated by the saved 2498 * value of a MDB2 object in $ active_connections[$connection_name], and2708 * value of a MDB2 object in $connection_pool[$connection_name], and 2499 2709 * {@link force_reconnect} is not true, then set the database 2500 2710 * fetch mode and return. 2501 2711 * 2502 2712 * If there is no connection, open one and save a reference to 2503 * it in $ active_connections[$connection_name].2713 * it in $connection_pool[$connection_name]. 2504 2714 * 2505 2715 * @uses $db 2506 2716 * @uses $database_name 2507 2717 * @uses $force_reconnect 2508 * @uses $ active_connections2718 * @uses $connection_pool 2509 2719 * @uses is_error() 2510 2720 * @throws {@link ActiveRecordError} 2511 2721 */ 2512 function establish_connection() { 2513 $this->set_connection_name(); 2514 $connection =& self::$active_connections[$this->connection_name]; 2722 function establish_connection($connection_name = null, $read_only = false) { 2723 $connection_name = $this->get_connection_name($connection_name); 2724 if($read_only) { 2725 $connection =& self::$connection_pool_read_only[$connection_name]; 2726 } else { 2727 $connection =& self::$connection_pool[$connection_name]; 2728 } 2515 2729 if(!is_object($connection) || $this->force_reconnect) { 2516 2730 $connection_settings = array(); 2517 2731 $connection_options = array(); 2518 if(array_key_exists($ this->connection_name, self::$database_settings)) {2732 if(array_key_exists($connection_name, self::$database_settings)) { 2519 2733 # Use a different custom sections settings ? 2520 if(array_key_exists("use", self::$database_settings[$ this->connection_name])) {2521 $connection_settings = self::$database_settings[self::$database_settings[$ this->connection_name]['use']];2734 if(array_key_exists("use", self::$database_settings[$connection_name])) { 2735 $connection_settings = self::$database_settings[self::$database_settings[$connection_name]['use']]; 2522 2736 } else { 2523 2737 # Custom defined db settings in database.ini 2524 $connection_settings = self::$database_settings[$ this->connection_name];2738 $connection_settings = self::$database_settings[$connection_name]; 2525 2739 } 2526 2740 } else { 2527 2741 # Just use the current environment's db settings 2528 # $ this->connection_name's default value is 'development' so2529 # i fshould never really get here unless you override $this->connection_name2742 # $connection_name's default value is 'development' so 2743 # it should never really get here unless you override $this->connection_name 2530 2744 # and you define a custom db section in database.ini and it can't find it. 2531 $connection_settings = self::$database_settings[$ this->connection_name];2745 $connection_settings = self::$database_settings[$connection_name]; 2532 2746 } 2533 2747 # Override database name if param is set … … 2541 2755 # Connect to the database and throw an error if the connect fails. 2542 2756 $connection =& MDB2::Connect($connection_settings, $connection_options); 2543 //static $connect_cnt; $connect_cnt++; error_log("connection#".$connect_cnt);2757 #static $connect_cnt; $connect_cnt++; error_log("establish_connection($connection_name, $read_only) #".$connect_cnt); 2544 2758 2545 2759 # For Postgres schemas (http://www.postgresql.org/docs/8.0/interactive/ddl-schemas.html) … … 2553 2767 } 2554 2768 if(!$this->is_error($connection)) { 2555 self::$active_connections[$this->connection_name] =& $connection; 2556 self::$db =& $connection; 2557 self::$db->setFetchMode($this->fetch_mode); 2769 $connection->setFetchMode($this->fetch_mode); 2770 if($read_only) { 2771 self::$connection_pool_read_only[$connection_name] =& $connection; 2772 $this->read_only_connection_name = $connection_name; 2773 } else { 2774 self::$connection_pool[$connection_name] =& $connection; 2775 $this->connection_name = $connection_name; 2776 } 2558 2777 } else { 2559 2778 $this->raise($connection->getMessage()); 2560 2779 } 2561 return self::$db;2780 return $connection; 2562 2781 } 2563 2782 … … 2565 2784 * Set the name of the database connection to use. 2566 2785 */ 2567 function set_connection_name() { 2568 $connection_name = null; 2569 if(!is_null($this->connection_name)) { 2570 $connection_name = $this->connection_name; 2571 } else { 2572 $connection_name = self::$environment ? self::$environment : 'development'; 2573 } 2574 $this->connection_name = $connection_name; 2786 function get_connection_name($connection_name = null) { 2787 if(is_null($connection_name)) { 2788 if(!is_null($this->connection_name)) { 2789 $connection_name = $this->connection_name; 2790 } else { 2791 $connection_name = self::$environment ? self::$environment : 'development'; 2792 } 2793 } 2794 return $connection_name; 2795 } 2796 /** 2797 * Gets the database connection whether its read only or read/write 2798 */ 2799 function get_connection($read_only = false) { 2800 if($read_only && $this->read_only_connection_name && 2801 array_key_exists($this->read_only_connection_name, self::$connection_pool_read_only)) { 2802 $db =& self::$connection_pool_read_only[$this->read_only_connection_name]; 2803 #error_log("get_connection($read_only) - using read only:".$this->read_only_connection_name); 2804 } elseif(array_key_exists($this->connection_name, self::$connection_pool)) { 2805 $db =& self::$connection_pool[$this->connection_name]; 2806 #error_log("get_connection($read_only) - using read/write from pool:".$this->connection_name); 2807 } else { 2808 $db =& self::$db; 2809 #error_log("get_connection($read_only) - using read/write default:".$this->connection_name); 2810 } 2811 return $db; 2575 2812 } 2576 2813 … … 2703 2940 # Mark the corresponding entry in the error array by 2704 2941 # putting the error message in for the attribute, 2705 # e.g. $this-> errors['name'] = "can't be empty"2942 # e.g. $this->add_error("can't be empty", 'name'); 2706 2943 # when 'name' was an empty string. 2707 $this-> errors[$validate_on_attribute] = $result[1];2944 $this->add_error($result[1], $validate_on_attribute); 2708 2945 } 2709 2946 } … … 2716 2953 /** 2717 2954 * Overwrite this method for validation checks on all saves and 2718 * use $this->errors[] = "My error message."; or 2719 * for invalid attributes $this->errors['attribute'] = "Attribute is invalid."; 2955 * use $this->add_error("My error message.", 'attribute'); 2720 2956 * @todo Document this API 2721 2957 */ … … 2810 3046 * @todo Document this API 2811 3047 */ 2812 function before_delete() { }3048 function before_delete() { return true; } 2813 3049 2814 3050 /** … … 2845 3081 if(method_exists($this, $method_name) && is_array($validation_name)) { 2846 3082 foreach($validation_name as $attribute_name => $options) { 2847 if( !is_array($options)) {3083 if(is_string($options)) { 2848 3084 $attribute_name = $options; 2849 3085 $options = array(); 2850 } 3086 } elseif(!is_array($options)) { 3087 $options = array(); 3088 } 2851 3089 $attribute_name = trim($attribute_name); 2852 3090 $parameters = array(); 2853 $on = array_key_exists('on', $options) ? 2854 $options['on'] : 'save'; 2855 $message = array_key_exists('message', $options) ? 2856 $options['message'] : null; 3091 $on = array_key_exists('on', $options) ? $options['on'] : 'save'; 3092 $message = array_key_exists('message', $options) ? $options['message'] : null; 2857 3093 switch($method_name) { 2858 3094 case 'validates_acceptance_of': … … 2923 3159 foreach((array) $attribute_names as $attribute_name) { 2924 3160 if($this->$attribute_name != $accept) { 2925 $attribute_human = Inflector::humanize($attribute_name); 2926 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3161 #$attribute_human = $this->human_attribute_name($attribute_name); 3162 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3163 $this->add_error($message, $attribute_name); 2927 3164 } 2928 3165 } … … 2941 3178 $attribute_confirmation = $attribute_name . '_confirmation'; 2942 3179 if($this->$attribute_confirmation != $this->$attribute_name) { 2943 $attribute_human = Inflector::humanize($attribute_name); 2944 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3180 #$attribute_human = $this->human_attribute_name($attribute_name); 3181 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3182 $this->add_error($message, $attribute_name); 2945 3183 } 2946 3184 } … … 2961 3199 list($minimum, $maximum) = explode('..', $in); 2962 3200 if($this->$attribute_name >= $minimum && $this->$attribute_name <= $maximum) { 2963 $attribute_human = Inflector::humanize($attribute_name); 2964 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3201 #$attribute_human = $this->human_attribute_name($attribute_name); 3202 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3203 $this->add_error($message, $attribute_name); 2965 3204 } 2966 3205 } elseif(is_array($in)) { 2967 3206 if(in_array($this->$attribute_name, $in)) { 2968 $attribute_human = Inflector::humanize($attribute_name); 2969 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3207 #$attribute_human = $this->human_attribute_name($attribute_name); 3208 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3209 $this->add_error($message, $attribute_name); 2970 3210 } 2971 3211 } … … 2987 3227 # Was there an error? 2988 3228 if(!preg_match($regex, $value)) { 2989 $attribute_human = Inflector::humanize($attribute_name); 2990 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3229 #$attribute_human = $this->human_attribute_name($attribute_name); 3230 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3231 $this->add_error($message, $attribute_name); 2991 3232 } 2992 3233 } … … 3007 3248 list($minimum, $maximum) = explode('..', $in); 3008 3249 if(!($this->$attribute_name >= $minimum && $this->$attribute_name <= $maximum)) { 3009 $attribute_human = Inflector::humanize($attribute_name); 3010 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3250 #$attribute_human = $this->human_attribute_name($attribute_name); 3251 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3252 $this->add_error($message, $attribute_name); 3011 3253 } 3012 3254 } elseif(is_array($in)) { 3013 3255 if(!in_array($this->$attribute_name, $in)) { 3014 $attribute_human = Inflector::humanize($attribute_name); 3015 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3256 #$attribute_human = $this->human_attribute_name($attribute_name); 3257 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3258 $this->add_error($message, $attribute_name); 3016 3259 } 3017 3260 } … … 3042 3285 # Attribute string length 3043 3286 $len = strlen($this->$attribute_name); 3044 $attribute_human = Inflector::humanize($attribute_name);3287 #$attribute_human = $this->human_attribute_name($attribute_name); 3045 3288 3046 3289 # If you have set the min length option … … 3048 3291 $message = $this->get_error_message_for_validation($options['too_short'], 'too_short', $options['minimum']); 3049 3292 if($len < $options['minimum']) { 3050 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3293 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3294 $this->add_error($message, $attribute_name); 3051 3295 } 3052 3296 } … … 3056 3300 $message = $this->get_error_message_for_validation($options['too_long'], 'too_long', $options['maximum']); 3057 3301 if($len > $options['maximum']) { 3058 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3302 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3303 $this->add_error($message, $attribute_name); 3059 3304 } 3060 3305 } … … 3064 3309 $message = $this->get_error_message_for_validation($options['wrong_length'], 'wrong_length', $options['is']); 3065 3310 if($len != $options['is']) { 3066 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3311 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3312 $this->add_error($message, $attribute_name); 3067 3313 } 3068 3314 } … … 3087 3333 $message = $this->get_error_message_for_validation($message, 'not_an_integer'); 3088 3334 if(!is_integer($value)) { 3089 $attribute_human = Inflector::humanize($attribute_name); 3090 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3335 #$attribute_human = $this->human_attribute_name($attribute_name); 3336 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3337 $this->add_error($message, $attribute_name); 3091 3338 } 3092 3339 } else { 3093 3340 $message = $this->get_error_message_for_validation($message, 'not_a_number'); 3094 3341 if(!is_numeric($value)) { 3095 $attribute_human = Inflector::humanize($attribute_name); 3096 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3342 #$attribute_human = $this->human_attribute_name($attribute_name); 3343 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3344 $this->add_error($message, $attribute_name); 3097 3345 } 3098 3346 } … … 3111 3359 foreach((array) $attribute_names as $attribute_name) { 3112 3360 if($this->$attribute_name === '' || is_null($this->$attribute_name)) { 3113 $attribute_human = Inflector::humanize($attribute_name); 3114 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3361 #$attribute_human = $this->human_attribute_name($attribute_name); 3362 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3363 $this->add_error($message, $attribute_name); 3115 3364 } 3116 3365 } … … 3136 3385 } 3137 3386 if($this->find_first($conditions)) { 3138 $attribute_human = Inflector::humanize($attribute_name); 3139 $this->add_error("{$attribute_human} {$message}", $attribute_name); 3387 #$attribute_human = $this->human_attribute_name($attribute_name); 3388 #$this->add_error("{$attribute_human} {$message}", $attribute_name); 3389 $this->add_error($message, $attribute_name); 3140 3390 } 3141 3391 } … … 3184 3434 throw new ActiveRecordError($error_message, "ActiveRecord Error", "500"); 3185 3435 } 3436 3437 function errors_full_messages() { 3438 $full_messages = array(); 3439 foreach((array)$this->errors as $attribute => $message) { 3440 if(is_null($message)) { 3441 continue; 3442 } 3443 $full_messages[] = $this->human_attribute_name($attribute) . " " . $message; 3444 } 3445 return $full_messages; 3446 } 3447 3448 function errors_on($attribute) { 3449 $errors = isset($this->errors[$attribute]) ? $this->errors[$attribute] : null; 3450 return ((is_array($errors) && count($errors) == 1) ? current($errors) : $errors); 3451 } 3186 3452 3187 3453 /**
