- Timestamp:
- 06/15/09 22:55:43 (1 year ago)
- Files:
-
- fActiveRecord.php (modified) (58 diffs)
- fDatabase.php (modified) (4 diffs)
- fGrammar.php (modified) (11 diffs)
- fORM.php (modified) (21 diffs)
- fORMColumn.php (modified) (5 diffs)
- fORMFile.php (modified) (2 diffs)
- fORMOrdering.php (modified) (2 diffs)
- fORMRelated.php (modified) (25 diffs)
- fORMSchema.php (modified) (4 diffs)
- fORMValidation.php (modified) (16 diffs)
- fSchema.php (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
fActiveRecord.php
r600 r603 Hide Line Numbers 16 16 * @link http://flourishlib.com/fActiveRecord 17 17 * 18 * @version 1.0.0b20 18 * @version 1.0.0b21 19 * @changes 1.0.0b21 Performance tweaks and updates for fORM and fORMRelated API changes [wb, 2009-06-15] 19 20 * @changes 1.0.0b20 Changed replacement values in preg_replace() calls to be properly escaped [wb, 2009-06-11] 20 21 * @changes 1.0.0b19 Added `list{RelatedRecords}()` methods, updated code for new fORMRelated API [wb, 2009-06-02] … … 265 266 public function __call($method_name, $parameters) 266 267 { 267 if ($callback = fORM::getActiveRecordMethod($this, $method_name)) { 268 $class = get_class($this); 269 270 if ($callback = fORM::getActiveRecordMethod($class, $method_name)) { 268 271 return call_user_func_array( 269 272 $callback, … … 326 329 327 330 if (isset($parameters[1])) { 328 return fORMRelated::associateRecords($ this, $this->related_records, $subject, $parameters[0], $parameters[1]);329 } 330 return fORMRelated::associateRecords($ this, $this->related_records, $subject, $parameters[0]);331 return fORMRelated::associateRecords($class, $this->related_records, $subject, $parameters[0], $parameters[1]); 332 } 333 return fORMRelated::associateRecords($class, $this->related_records, $subject, $parameters[0]); 331 334 332 335 case 'build': … … 335 338 336 339 if (isset($parameters[0])) { 337 return fORMRelated::buildRecords($ this, $this->values, $this->related_records, $subject, $parameters[0]);338 } 339 return fORMRelated::buildRecords($ this, $this->values, $this->related_records, $subject);340 return fORMRelated::buildRecords($class, $this->values, $this->related_records, $subject, $parameters[0]); 341 } 342 return fORMRelated::buildRecords($class, $this->values, $this->related_records, $subject); 340 343 341 344 case 'count': … … 344 347 345 348 if (isset($parameters[0])) { 346 return fORMRelated::countRecords($ this, $this->values, $this->related_records, $subject, $parameters[0]);347 } 348 return fORMRelated::countRecords($ this, $this->values, $this->related_records, $subject);349 return fORMRelated::countRecords($class, $this->values, $this->related_records, $subject, $parameters[0]); 350 } 351 return fORMRelated::countRecords($class, $this->values, $this->related_records, $subject); 349 352 350 353 case 'create': … … 352 355 353 356 if (isset($parameters[0])) { 354 return fORMRelated::createRecord($ this, $this->values, $subject, $parameters[0]);355 } 356 return fORMRelated::createRecord($ this, $this->values, $subject);357 return fORMRelated::createRecord($class, $this->values, $subject, $parameters[0]); 358 } 359 return fORMRelated::createRecord($class, $this->values, $subject); 357 360 358 361 case 'inject': … … 361 364 362 365 if (isset($parameters[1])) { 363 return fORMRelated::setRecordSet($ this, $this->related_records, $subject, $parameters[0], $parameters[1]);364 } 365 return fORMRelated::setRecordSet($ this, $this->related_records, $subject, $parameters[0]);366 return fORMRelated::setRecordSet($class, $this->related_records, $subject, $parameters[0], $parameters[1]); 367 } 368 return fORMRelated::setRecordSet($class, $this->related_records, $subject, $parameters[0]); 366 369 367 370 case 'link': … … 370 373 371 374 if (isset($parameters[0])) { 372 return fORMRelated::linkRecords($ this, $this->related_records, $subject, $parameters[0]);373 } 374 return fORMRelated::linkRecords($ this, $this->related_records, $subject);375 return fORMRelated::linkRecords($class, $this->related_records, $subject, $parameters[0]); 376 } 377 return fORMRelated::linkRecords($class, $this->related_records, $subject); 375 378 376 379 case 'list': … … 379 382 380 383 if (isset($parameters[0])) { 381 return fORMRelated::getPrimaryKeys($ this, $this->values, $this->related_records, $subject, $parameters[0]);382 } 383 return fORMRelated::getPrimaryKeys($ this, $this->values, $this->related_records, $subject);384 return fORMRelated::getPrimaryKeys($class, $this->values, $this->related_records, $subject, $parameters[0]); 385 } 386 return fORMRelated::getPrimaryKeys($class, $this->values, $this->related_records, $subject); 384 387 385 388 case 'populate': … … 388 391 389 392 if (isset($parameters[0])) { 390 return fORMRelated::populateRecords($ this, $this->related_records, $subject, $parameters[0]);391 } 392 return fORMRelated::populateRecords($ this, $this->related_records, $subject);393 return fORMRelated::populateRecords($class, $this->related_records, $subject, $parameters[0]); 394 } 395 return fORMRelated::populateRecords($class, $this->related_records, $subject); 393 396 394 397 case 'tally': … … 397 400 398 401 if (isset($parameters[1])) { 399 return fORMRelated::setCount($ this, $this->related_records, $subject, $parameters[0], $parameters[1]);400 } 401 return fORMRelated::setCount($ this, $this->related_records, $subject, $parameters[0]);402 return fORMRelated::setCount($class, $this->related_records, $subject, $parameters[0], $parameters[1]); 403 } 404 return fORMRelated::setCount($class, $this->related_records, $subject, $parameters[0]); 402 405 403 406 // Error handler … … 426 429 public function __clone() 427 430 { 431 $class = get_class($this); 432 428 433 // Copy values and cache, making sure objects are cloned to prevent reference issues 429 434 $temp_values = $this->values; … … 431 436 $this->values =& $new_values; 432 437 foreach ($temp_values as $column => $value) { 433 $this->values[$column] = fORM::replicate($ this, $column, $value);438 $this->values[$column] = fORM::replicate($class, $column, $value); 434 439 } 435 440 … … 458 463 459 464 // If we have a single auto incrementing primary key, remove the value 460 $table = fORM::tablize($ this);465 $table = fORM::tablize($class); 461 466 $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary'); 462 467 … … 500 505 } 501 506 502 if (fORM::getActiveRecordMethod($ this, '__construct')) {507 if (fORM::getActiveRecordMethod($class, '__construct')) { 503 508 return $this->__call('__construct', array($key)); 504 509 } … … 516 521 } elseif ($key !== NULL) { 517 522 518 $pk_columns = fORMSchema::retrieve()->getKeys(fORM::tablize($this), 'primary'); 523 $table = fORM::tablize($class); 524 $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary'); 519 525 520 526 // If the primary key does not look properly formatted, check to see if it is a UNIQUE key 521 527 $is_unique_key = FALSE; 522 528 if (is_array($key) && (sizeof($pk_columns) == 1 || array_keys($key) != $pk_columns)) { 523 $unique_keys = fORMSchema::retrieve()->getKeys( fORM::tablize($this), 'unique');529 $unique_keys = fORMSchema::retrieve()->getKeys($table, 'unique'); 524 530 $key_keys = array_keys($key); 525 531 foreach ($unique_keys as $unique_key) { … … 537 543 throw new fProgrammerException( 538 544 'An invalidly formatted primary or unique key was passed to this %s object', 539 fORM::getRecordName($ this)545 fORM::getRecordName($class) 540 546 ); 541 547 } … … 569 575 // Create an empty array for new objects 570 576 } else { 571 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($ this));577 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($class)); 572 578 foreach ($column_info as $column => $info) { 573 579 $this->values[$column] = NULL; … … 577 583 $this->old_values, 578 584 $column, 579 fORM::objectify($ this, $column, $info['default'])585 fORM::objectify($class, $column, $info['default']) 580 586 ); 581 587 } … … 584 590 585 591 fORM::callHookCallbacks( 586 $ this,592 $class, 587 593 'post::__construct()', 588 594 $this->values, … … 646 652 protected function constructInsertSQL($sql_values) 647 653 { 648 $sql = 'INSERT INTO ' . fORM::tablize( $this) . ' (';654 $sql = 'INSERT INTO ' . fORM::tablize(get_class($this)) . ' ('; 649 655 650 656 $columns = ''; … … 671 677 protected function constructUpdateSQL($sql_values) 672 678 { 673 $table = fORM::tablize( $this);679 $table = fORM::tablize(get_class($this)); 674 680 675 681 $sql = 'UPDATE ' . $table . ' SET '; … … 696 702 public function delete() 697 703 { 698 if (fORM::getActiveRecordMethod($this, 'delete')) { 704 $class = get_class($this); 705 706 if (fORM::getActiveRecordMethod($class, 'delete')) { 699 707 return $this->__call('delete', array()); 700 708 } … … 703 711 throw new fProgrammerException( 704 712 'This %s object does not yet exist in the database, and thus can not be deleted', 705 fORM::getRecordName($ this)713 fORM::getRecordName($class) 706 714 ); 707 715 } … … 715 723 ); 716 724 717 $table = fORM::tablize($this);725 $table = fORM::tablize($class); 718 726 719 727 $inside_db_transaction = fORMDatabase::retrieve()->isInsideTransaction(); … … 780 788 sprintf( 781 789 "<p>%1\$s</p>\n<ul>\n<li>%2\$s</li>\n</ul>", 782 self::compose('This %s can not be deleted because:', fORM::getRecordName($ this)),790 self::compose('This %s can not be deleted because:', fORM::getRecordName($class)), 783 791 join("</li>\n<li>", $restriction_messages) 784 792 ) … … 825 833 // If we just deleted an object that has an auto-incrementing primary key, 826 834 // lets delete that value from the object since it is no longer valid 827 $column_info = fORMSchema::retrieve()->getColumnInfo($table);828 835 $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary'); 829 if (sizeof($pk_columns) == 1 && $column_info[$pk_columns[0]]['auto_increment']) {836 if (sizeof($pk_columns) == 1 && fORMSchema::retrieve()->getColumnInfo($table, $pk_columns[0], 'auto_increment')) { 830 837 $this->values[$pk_columns[0]] = NULL; 831 838 unset($this->old_values[$pk_columns[0]]); … … 849 856 if ($e instanceof fValidationException) { 850 857 $message = $e->getMessage(); 851 $search = self::compose('This %s can not be deleted because:', fORM::getRecordName($ this));858 $search = self::compose('This %s can not be deleted because:', fORM::getRecordName($class)); 852 859 if (stripos($message, $search) === FALSE) { 853 860 $regex = self::compose('This %s can not be deleted because:', '__'); … … 855 862 $regex = '#(' . preg_quote($regex_parts[0], '#') . ').*?(' . preg_quote($regex_parts[0], '#') . ')#'; 856 863 857 $message = preg_replace($regex, '\1' . strtr(fORM::getRecordName($ this), array('\\' => '\\\\', '$' => '\\$')) . '\2', $message);864 $message = preg_replace($regex, '\1' . strtr(fORM::getRecordName($class), array('\\' => '\\\\', '$' => '\\$')) . '\2', $message); 858 865 859 866 $find = self::compose("One or more %s references it", '__'); … … 909 916 } 910 917 911 $column_type = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($this), $column, 'type'); 918 $table = fORM::tablize(get_class($this)); 919 $column_type = fORMSchema::retrieve()->getColumnInfo($table, $column, 'type'); 912 920 913 921 // Ensure the programmer is calling the function properly … … 950 958 // Make sure we don't mangle a non-float value 951 959 if ($column_type == 'float' && is_numeric($value)) { 952 $column_decimal_places = fORMSchema::retrieve()->getColumnInfo( fORM::tablize($this), $column, 'decimal_places');960 $column_decimal_places = fORMSchema::retrieve()->getColumnInfo($table, $column, 'decimal_places'); 953 961 954 962 // If the user passed in a formatting value, use it … … 981 989 public function exists() 982 990 { 983 if (fORM::getActiveRecordMethod($this, 'exists')) { 991 $class = get_class($this); 992 993 if (fORM::getActiveRecordMethod($class, 'exists')) { 984 994 return $this->__call('exists', array()); 985 995 } 986 996 987 $pk_columns = fORMSchema::retrieve()->getKeys(fORM::tablize($ this), 'primary');997 $pk_columns = fORMSchema::retrieve()->getKeys(fORM::tablize($class), 'primary'); 988 998 $exists = FALSE; 989 999 … … 1009 1019 protected function fetchResultFromUniqueKey($values) 1010 1020 { 1021 $class = get_class($this); 1011 1022 try { 1012 1023 if ($values === array_combine(array_keys($values), array_fill(0, sizeof($values), NULL))) { … … 1014 1025 } 1015 1026 1016 $table = fORM::tablize($ this);1027 $table = fORM::tablize($class); 1017 1028 $sql = 'SELECT * FROM ' . $table . ' WHERE '; 1018 1029 $conditions = array(); … … 1028 1039 throw new fNotFoundException( 1029 1040 'The %s requested could not be found', 1030 fORM::getRecordName($ this)1041 fORM::getRecordName($class) 1031 1042 ); 1032 1043 } … … 1043 1054 */ 1044 1055 protected function get($column) 1056 { 1057 if (!isset($this->values[$column]) && !array_key_exists($column, $this->values)) { 1058 throw new fProgrammerException( 1059 'The column specified, %s, does not exist', 1060 $column 1061 ); 1062 } 1063 return $this->values[$column]; 1064 } 1065 1066 1067 /** 1068 * Takes a row of data or a primary key and makes a hash from the primary key 1069 * 1070 * @param mixed $data An array of the records data, an array of primary key data or a scalar primary key value 1071 * @return string A hash of the record's primary key value 1072 */ 1073 protected function hash($data) 1074 { 1075 $class = get_class($this); 1076 $pk_columns = fORMSchema::retrieve()->getKeys(fORM::tablize(get_class($this)), 'primary'); 1077 1078 // Build an array of just the primary key data 1079 $pk_data = array(); 1080 foreach ($pk_columns as $pk_column) { 1081 $pk_data[$pk_column] = fORM::scalarize( 1082 $class, 1083 $pk_column, 1084 is_array($data) ? $data[$pk_column] : $data 1085 ); 1086 if (is_numeric($pk_data[$pk_column]) || is_object($pk_data[$pk_column])) { 1087 $pk_data[$pk_column] = (string) $pk_data[$pk_column]; 1088 } 1089 } 1090 1091 return md5(serialize($pk_data)); 1092 } 1093 1094 1095 /** 1096 * Retrieves information about a column 1097 * 1098 * @param string $column The name of the column to inspect 1099 * @param string $element The metadata element to retrieve 1100 * @return mixed The metadata array for the column, or the metadata element specified 1101 */ 1102 protected function inspect($column, $element=NULL) 1045 1103 { 1046 1104 if (!array_key_exists($column, $this->values)) { … … 1050 1108 ); 1051 1109 } 1052 return $this->values[$column]; 1053 } 1054 1055 1056 /** 1057 * Takes a row of data or a primary key and makes a hash from the primary key 1058 * 1059 * @param mixed $data An array of the records data, an array of primary key data or a scalar primary key value 1060 * @return string A hash of the record's primary key value 1061 */ 1062 protected function hash($data) 1063 { 1064 $pk_columns = fORMSchema::retrieve()->getKeys(fORM::tablize($this), 'primary'); 1065 1066 // Build an array of just the primary key data 1067 $pk_data = array(); 1068 foreach ($pk_columns as $pk_column) { 1069 $pk_data[$pk_column] = fORM::scalarize( 1070 $this, 1071 $pk_column, 1072 is_array($data) ? $data[$pk_column] : $data 1073 ); 1074 if (is_numeric($pk_data[$pk_column]) || is_object($pk_data[$pk_column])) { 1075 $pk_data[$pk_column] = (string) $pk_data[$pk_column]; 1076 } 1077 } 1078 1079 return md5(serialize($pk_data)); 1080 } 1081 1082 1083 /** 1084 * Retrieves information about a column 1085 * 1086 * @param string $column The name of the column to inspect 1087 * @param string $element The metadata element to retrieve 1088 * @return mixed The metadata array for the column, or the metadata element specified 1089 */ 1090 protected function inspect($column, $element=NULL) 1091 { 1092 if (!array_key_exists($column, $this->values)) { 1093 throw new fProgrammerException( 1094 'The column specified, %s, does not exist', 1095 $column 1096 ); 1097 } 1098 1099 $info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($this), $column); 1110 1111 $info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize(get_class($this)), $column); 1100 1112 1101 1113 if (!in_array($info['type'], array('varchar', 'char', 'text'))) { … … 1138 1150 public function load() 1139 1151 { 1140 if (fORM::getActiveRecordMethod($this, 'load')) { 1152 $class = get_class($this); 1153 1154 if (fORM::getActiveRecordMethod($class, 'load')) { 1141 1155 return $this->__call('load', array()); 1142 1156 } 1143 1157 1144 1158 try { 1145 $table = fORM::tablize($ this);1159 $table = fORM::tablize($class); 1146 1160 $sql = 'SELECT * FROM ' . $table . ' WHERE ' . fORMDatabase::createPrimaryKeyWhereClause($table, $table, $this->values, $this->old_values); 1147 1161 … … 1152 1166 throw new fNotFoundException( 1153 1167 'The %s requested could not be found', 1154 fORM::getRecordName($ this)1168 fORM::getRecordName($class) 1155 1169 ); 1156 1170 } … … 1170 1184 protected function loadFromResult($result) 1171 1185 { 1186 $class = get_class($this); 1172 1187 $row = $result->current(); 1173 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($this)); 1188 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($class)); 1189 1190 $db = fORMDatabase::retrieve(); 1174 1191 1175 1192 foreach ($row as $column => $value) { 1176 if ($value === NULL) { 1177 $this->values[$column] = $value; 1178 } else { 1179 $this->values[$column] = fORMDatabase::retrieve()->unescape($column_info[$column]['type'], $value); 1180 } 1181 1182 $this->values[$column] = fORM::objectify($this, $column, $this->values[$column]); 1193 if ($value !== NULL) { 1194 $value = $db->unescape($column_info[$column]['type'], $value); 1195 } 1196 1197 $this->values[$column] = fORM::objectify($class, $column, $value); 1183 1198 } 1184 1199 1185 1200 // Save this object to the identity map 1186 $class = get_class($this);1187 1201 $hash = $this->hash($row); 1188 1202 … … 1247 1261 public function populate() 1248 1262 { 1249 if (fORM::getActiveRecordMethod($this, 'populate')) { 1263 $class = get_class($this); 1264 1265 if (fORM::getActiveRecordMethod($class, 'populate')) { 1250 1266 return $this->__call('populate', array()); 1251 1267 } … … 1260 1276 ); 1261 1277 1262 $table = fORM::tablize($ this);1278 $table = fORM::tablize($class); 1263 1279 1264 1280 $column_info = fORMSchema::retrieve()->getColumnInfo($table); … … 1308 1324 } 1309 1325 1310 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize( $this), $column);1326 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize(get_class($this)), $column); 1311 1327 $column_type = $column_info['type']; 1312 1328 1313 1329 // Ensure the programmer is calling the function properly 1314 if ( in_array($column_type, array('blob'))) {1330 if ($column_type == 'blob') { 1315 1331 throw new fProgrammerException( 1316 1332 'The column specified, %s, can not be prepared because it is a blob column', … … 1397 1413 $signatures = array(); 1398 1414 1399 $columns_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($this)); 1415 $class = get_class($this); 1416 $columns_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($class)); 1400 1417 foreach ($columns_info as $column => $column_info) { 1401 1418 $camelized_column = fGrammar::camelize($column, TRUE); … … 1552 1569 } 1553 1570 1554 fORMRelated::reflect($ this, $signatures, $include_doc_comments);1571 fORMRelated::reflect($class, $signatures, $include_doc_comments); 1555 1572 1556 1573 fORM::callReflectCallbacks($this, $signatures, $include_doc_comments); 1557 1574 1558 $reflection = new ReflectionClass( get_class($this));1575 $reflection = new ReflectionClass($class); 1559 1576 $methods = $reflection->getMethods(); 1560 1577 … … 1663 1680 $class = get_class($this); 1664 1681 $hash = self::hash($this->values); 1665 1682 $table = fORM::tablize($class); 1683 1666 1684 // If the object has not been replicated yet, do it now 1667 1685 if (!isset(fActiveRecord::$replicate_map[$class])) { … … 1672 1690 1673 1691 // We need the primary key to get a hash, otherwise certain recursive relationships end up losing members 1674 $table = fORM::tablize($class);1675 1692 $pk_columns = fORMSchema::retrieve()->getKeys($table, 'primary'); 1676 1693 if (sizeof($pk_columns) == 1 && fORMSchema::retrieve()->getColumnInfo($table, $pk_columns[0], 'auto_increment')) { … … 1682 1699 1683 1700 $parameters = func_get_args(); 1684 1685 $table = fORM::tablize($this);1686 1701 1687 1702 $recursive = FALSE; … … 1741 1756 'The related class specified, %1$s, does not appear to be in a many-to-many or one-to-many relationship with %$2s', 1742 1757 $parameter, 1743 fORM::getClass($this)1758 get_class($this) 1744 1759 ); 1745 1760 } 1746 1761 1747 1762 // Get the related records 1748 $record_set = fORMRelated::buildRecords($ this, $this->values, $this->related_records, $related_class, $route);1763 $record_set = fORMRelated::buildRecords($class, $this->values, $this->related_records, $related_class, $route); 1749 1764 1750 1765 // One-to-many records need to be replicated, possibly recursively … … 1763 1778 1764 1779 // Cause the related records to be associated with the new clone 1765 fORMRelated::associateRecords($ this, $clone->related_records, $related_class, $record_set, $route);1780 fORMRelated::associateRecords($class, $clone->related_records, $related_class, $record_set, $route); 1766 1781 } 1767 1782 … … 1807 1822 } 1808 1823 1809 $value = fORM::objectify($this, $column, $value); 1824 $class = get_class($this); 1825 $value = fORM::objectify($class, $column, $value); 1810 1826 1811 1827 // Float and int columns that look like numbers with commas will have the commas removed 1812 1828 if (is_string($value)) { 1813 $table = fORM::tablize($ this);1829 $table = fORM::tablize($class); 1814 1830 $type = fORMSchema::retrieve()->getColumnInfo($table, $column, 'type'); 1815 1831 if (in_array($type, array('integer', 'float')) && preg_match('#^(\d+,)+\d+(\.\d+)?$#', $value)) { … … 1834 1850 public function store() 1835 1851 { 1836 if (fORM::getActiveRecordMethod($this, 'store')) { 1852 $class = get_class($this); 1853 1854 if (fORM::getActiveRecordMethod($class, 'store')) { 1837 1855 return $this->__call('store', array()); 1838 1856 } … … 1848 1866 1849 1867 try { 1850 $table = fORM::tablize($ this);1868 $table = fORM::tablize($class); 1851 1869 $column_info = fORMSchema::retrieve()->getColumnInfo($table); 1852 1870 … … 1892 1910 $sql_values = array(); 1893 1911 foreach ($column_info as $column => $info) { 1894 $value = fORM::scalarize($ this, $column, $this->values[$column]);1912 $value = fORM::scalarize($class, $column, $this->values[$column]); 1895 1913 $sql_values[$column] = fORMDatabase::escapeBySchema($table, $column, $value); 1896 1914 } … … 1916 1934 1917 1935 // Storing *-to-many relationships 1918 fORMRelated::store($ this, $this->values, $this->related_records);1936 fORMRelated::store($class, $this->values, $this->related_records); 1919 1937 1920 1938 … … 1992 2010 public function validate($return_messages=FALSE) 1993 2011 { 1994 if (fORM::getActiveRecordMethod($this, 'validate')) { 2012 $class = get_class($this); 2013 2014 if (fORM::getActiveRecordMethod($class, 'validate')) { 1995 2015 return $this->__call('validate', array($return_messages)); 1996 2016 } … … 2012 2032 2013 2033 // Validate related records 2014 $related_validation_messages = fORMValidation::validateRelated($ this, $this->related_records);2034 $related_validation_messages = fORMValidation::validateRelated($class, $this->related_records); 2015 2035 2016 2036 $validation_messages = array_merge($validation_messages, $local_validation_messages, $related_validation_messages); … … 2026 2046 ); 2027 2047 2028 fORMValidation::reorderMessages($ this, $validation_messages);2048 fORMValidation::reorderMessages($class, $validation_messages); 2029 2049 2030 2050 if ($return_messages) { fDatabase.php
r600 r603 Hide Line Numbers 47 47 * @link http://flourishlib.com/fDatabase 48 48 * 49 * @version 1.0.0b11 49 * @version 1.0.0b12 50 * @changes 1.0.0b12 Updates to ::unescape() to improve performance [wb, 2009-06-15] 50 51 * @changes 1.0.0b11 Changed replacement values in preg_replace() calls to be properly escaped [wb, 2009-06-11] 51 52 * @changes 1.0.0b10 Changed date/time/timestamp escaping from `strtotime()` to fDate/fTime/fTimestamp for better localization support [wb, 2009-06-01] … … 2280 2281 2281 2282 switch ($data_type) { 2282 case 'blob': 2283 case '%l': 2284 $callback = $this->unescapeBlob; 2285 break; 2286 case 'boolean': 2287 case '%b': 2288 $callback = $this->unescapeBoolean; 2289 break; 2290 case 'date': 2291 case '%d': 2292 $callback = $this->unescapeDate; 2293 break; 2294 case 'float': 2295 case '%f': 2296 $callback = $this->unescapeFloat; 2297 break; 2298 case 'integer': 2299 case '%i': 2300 $callback = $this->unescapeInteger; 2301 break; 2283 // Testing showed that strings tend to be most common, 2284 // and moving this to the top of the switch statement 2285 // improved performance on read-heavy pages 2302 2286 case 'string': 2303 2287 case 'varchar': … … 2305 2289 case 'text': 2306 2290 case '%s': 2307 $callback = $this->unescapeString; 2291 return $value; 2292 2293 case 'boolean': 2294 case '%b': 2295 $callback = $this->unescapeBoolean; 2308 2296 break; 2297 2298 case 'date': 2299 case '%d': 2300 $callback = $this->unescapeDate; 2301 break; 2302 2303 case 'float': 2304 case '%f': 2305 return $value; 2306 2307 case 'integer': 2308 case '%i': 2309 return $value; 2310 2309 2311 case 'time': 2310 2312 case '%t': 2311 2313 $callback = $this->unescapeTime; 2312 2314 break; 2315 2313 2316 case 'timestamp': 2314 2317 case '%p': 2315 2318 $callback = $this->unescapeTimestamp; 2319 break; 2320 2321 case 'blob': 2322 case '%l': 2323 $callback = $this->unescapeBlob; 2316 2324 break; 2317 2325 } … … 2382 2390 } 2383 2391 return date('Y-m-d', strtotime($value)); 2384 }2385 2386 2387 /**2388 * Unescapes a float coming out of the database (included for completeness)2389 *2390 * @param string $value The value to unescape2391 * @return float The float2392 */2393 private function unescapeFloat($value)2394 {2395 return $value;2396 }2397 2398 2399 /**2400 * Unescapes an integer coming out of the database (included for completeness)2401 *2402 * @param string $value The value to unescape2403 * @return integer The integer2404 */2405 private function unescapeInteger($value)2406 {2407 return $value;2408 }2409 2410 2411 /**2412 * Unescapes a string coming out of the database (included for completeness)2413 *2414 * @param string $value The value to unescape2415 * @return string The string2416 */2417 private function unescapeString($value)2418 {2419 return $value;2420 2392 } 2421 2393 fGrammar.php
r600 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fGrammar 11 11 * 12 * @version 1.0.0b2 12 * @version 1.0.0b4 13 * @changes 1.0.0b4 Added caching for various methods - provided significant performance boost to ORM [wb, 2009-06-15] 13 14 * @changes 1.0.0b3 Changed replacement values in preg_replace() calls to be properly escaped [wb, 2009-06-11] 14 15 * @changes 1.0.0b2 Fixed a bug where some words would lose capitalization with ::pluralize() and ::singularize() [wb, 2009-01-25] … … 31 32 const underscorize = 'fGrammar::underscorize'; 32 33 34 35 /** 36 * Cache for plural <-> singular and underscore <-> camelcase 37 * 38 * @var array 39 */ 40 static private $cache = array( 41 'camelize' => array(0 => array(), 1 => array()), 42 'humanize' => array(), 43 'pluralize' => array(), 44 'singularize' => array(), 45 'underscorize' => array() 46 ); 33 47 34 48 /** … … 124 138 { 125 139 self::$humanize_rules[$non_humanized_string] = $humanized_string; 140 141 self::$cache['humanize'] = array(); 126 142 } 127 143 … … 139 155 self::$underscorize_rules[$camel_case] = $underscore_notation; 140 156 self::$camelize_rules[$underscore_notation] = $camel_case; 157 158 self::$cache['camelize'] = array(0 => array(), 1 => array()); 159 self::$cache['underscorize'] = array(); 141 160 } 142 161 … … 165 184 self::$plural_to_singular_rules 166 185 ); 186 187 self::$cache['pluralize'] = array(); 188 self::$cache['singularize'] = array(); 167 189 } 168 190 … … 177 199 static public function camelize($string, $upper) 178 200 { 201 $upper = (int) $upper; 202 if (isset(self::$cache['camelize'][$upper][$string])) { 203 return self::$cache['camelize'][$upper][$string]; 204 } 205 206 $original = $string; 207 179 208 // Handle custom rules 180 209 if (isset(self::$camelize_rules[$string])) { 181 $ camel= self::$camelize_rules[$string];210 $string = self::$camelize_rules[$string]; 182 211 if ($upper) { 183 returnstrtoupper($camel[0]) . substr($camel, 1);212 $string = strtoupper($camel[0]) . substr($camel, 1); 184 213 } 185 return $camel;186 }187 214 188 215 // Make a humanized string like underscore notation 189 if (strpos($string, ' ') !== FALSE) {216 } elseif (strpos($string, ' ') !== FALSE) { 190 217 $string = strtolower(preg_replace('#\s+#', '_', $string)); 191 }192 218 193 219 // Check to make sure this is not already camel case 194 if (strpos($string, '_') === FALSE) {220 } elseif (strpos($string, '_') === FALSE) { 195 221 if ($upper) { 196 222 $string = strtoupper($string[0]) . substr($string, 1); 197 223 } 198 return $string; 199 } 200 224 201 225 // Handle underscore notation 202 $string = strtolower($string); 203 if ($upper) { 204 $string = strtoupper($string[0]) . substr($string, 1); 205 } 206 return preg_replace('/(_([a-z0-9]))/e', 'strtoupper("\2")', $string); 226 } else { 227 $string = strtolower($string); 228 if ($upper) { 229 $string = strtoupper($string[0]) . substr($string, 1); 230 } 231 $string = preg_replace('/(_([a-z0-9]))/e', 'strtoupper("\2")', $string); 232 } 233 234 self::$cache['camelize'][$upper][$original] = $string; 235 return $string; 207 236 } 208 237 … … 216 245 static public function humanize($string) 217 246 { 247 if (isset(self::$cache['humanize'][$string])) { 248 return self::$cache['humanize'][$string]; 249 } 250 251 $original = $string; 252 218 253 if (isset(self::$humanize_rules[$string])) { 219 return self::$humanize_rules[$string]; 220 } 221 222 // If there is a space, it is already humanized 223 if (strpos($string, ' ') !== FALSE) { 224 return $string; 225 } 226 227 // If we don't have an underscore we probably have camelCase 228 if (strpos($string, '_') === FALSE) { 229 $string = self::underscorize($string); 230 } 231 232 return preg_replace( 233 '/(\b(api|css|gif|html|id|jpg|js|mp3|pdf|php|png|sql|swf|url|xhtml|xml)\b|\b\w)/e', 234 'strtoupper("\1")', 235 str_replace('_', ' ', $string) 236 ); 254 $string = self::$humanize_rules[$string]; 255 256 // If there is no space, it isn't already humanized 257 } elseif (strpos($string, ' ') === FALSE) { 258 259 // If we don't have an underscore we probably have camelCase 260 if (strpos($string, '_') === FALSE) { 261 $string = self::underscorize($string); 262 } 263 264 $string = preg_replace( 265 '/(\b(api|css|gif|html|id|jpg|js|mp3|pdf|php|png|sql|swf|url|xhtml|xml)\b|\b\w)/e', 266 'strtoupper("\1")', 267 str_replace('_', ' ', $string) 268 ); 269 } 270 271 self::$cache['humanize'][$original] = $string; 272 273 return $string; 237 274 } 238 275 … … 347 384 static public function pluralize($singular_noun) 348 385 { 386 if (isset(self::$cache['pluralize'][$singular_noun])) { 387 return self::$cache['pluralize'][$singular_noun]; 388 } 389 390 $original = $singular_noun; 391 $plural_noun = NULL; 392 349 393 list ($beginning, $singular_noun) = self::splitLastWord($singular_noun); 350 394 foreach (self::$singular_to_plural_rules as $from => $to) { 351 395 if (preg_match('#' . $from . '#iD', $singular_noun)) { 352 return $beginning . preg_replace('#' . $from . '#iD', $to, $singular_noun); 396 $plural_noun = $beginning . preg_replace('#' . $from . '#iD', $to, $singular_noun); 397 break; 353 398 } 354 399 } 355 throw new fProgrammerException('The noun specified could not be pluralized'); 400 401 if (!$plural_noun) { 402 throw new fProgrammerException('The noun specified could not be pluralized'); 403 } 404 405 self::$cache['pluralize'][$original] = $plural_noun; 406 407 return $plural_noun; 356 408 } 357 409 … … 384 436 static public function reset() 385 437 { 386 self::$camelize_rules = array(); 438 self::$cache = array( 439 'camelize' => array(0 => array(), 1 => array()), 440 'humanize' => array(), 441 'pluralize' => array(), 442 'singularize' => array(), 443 'underscorize' => array() 444 ); 445 self::$camelize_rules = array(); 387 446 self::$humanize_rules = array(); 388 447 self::$join_array_callback = NULL; … … 439 498 static public function singularize($plural_noun) 440 499 { 500 if (isset(self::$cache['singularize'][$plural_noun])) { 501 return self::$cache['singularize'][$plural_noun]; 502 } 503 504 $original = $plural_noun; 505 $singular_noun = NULL; 506 441 507 list ($beginning, $plural_noun) = self::splitLastWord($plural_noun); 442 508 foreach (self::$plural_to_singular_rules as $from => $to) { 443 509 if (preg_match('#' . $from . '#iD', $plural_noun)) { 444 return $beginning . preg_replace('#' . $from . '#iD', $to, $plural_noun); 510 $singular_noun = $beginning . preg_replace('#' . $from . '#iD', $to, $plural_noun); 511 break; 445 512 } 446 513 } 447 throw new fProgrammerException('The noun specified could not be singularized'); 514 515 if (!$singular_noun) { 516 throw new fProgrammerException('The noun specified could not be singularized'); 517 } 518 519 self::$cache['singularize'][$original] = $singular_noun; 520 521 return $singular_noun; 448 522 } 449 523 … … 485 559 static public function underscorize($string) 486 560 { 561 if (isset(self::$cache['underscorize'][$string])) { 562 return self::$cache['underscorize'][$string]; 563 } 564 565 $original = $string; 487 566 $string = strtolower($string[0]) . substr($string, 1); 488 567 489 568 // Handle custom rules 490 569 if (isset(self::$underscorize_rules[$string])) { 491 return self::$underscorize_rules[$string]; 492 } 570 $string = self::$underscorize_rules[$string]; 493 571 494 572 // If the string is already underscore notation then leave it 495 if (strpos($string, '_') !== FALSE) { 496 return $string; 497 } 573 } elseif (strpos($string, '_') !== FALSE) { 498 574 499 575 // Allow humanized string to be passed in 500 if (strpos($string, ' ') !== FALSE) { 501 return strtolower(preg_replace('#\s+#', '_', $string)); 502 } 503 504 do { 505 $old_string = $string; 506 $string = preg_replace('/([a-zA-Z])([0-9])/', '\1_\2', $string); 507 $string = preg_replace('/([a-z0-9A-Z])([A-Z])/', '\1_\2', $string); 508 } while ($old_string != $string); 509 510 return strtolower($string); 576 } elseif (strpos($string, ' ') !== FALSE) { 577 $string = strtolower(preg_replace('#\s+#', '_', $string)); 578 579 } else { 580 do { 581 $old_string = $string; 582 $string = preg_replace('/([a-zA-Z])([0-9])/', '\1_\2', $string); 583 $string = preg_replace('/([a-z0-9A-Z])([A-Z])/', '\1_\2', $string); 584 } while ($old_string != $string); 585 586 $string = strtolower($string); 587 } 588 589 self::$cache['underscorize'][$original] = $string; 590 591 return $string; 511 592 } 512 593 fORM.php
r591 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fORM 11 11 * 12 * @version 1.0.0b8 12 * @version 1.0.0b9 13 * @changes 1.0.0b9 Added caching for performance and changed some method APIs to only allow class names instead of instances [wb, 2009-06-15] 13 14 * @changes 1.0.0b8 Updated documentation to reflect removal of `$associate` parameter for callbacks passed to ::registerRecordSetMethod() [wb, 2009-06-02] 14 15 * @changes 1.0.0b7 Added ::enableSchemaCaching() to replace fORMSchema::enableSmartCaching() [wb, 2009-05-04] … … 60 61 61 62 /** 63 * Cache for repetitive computation 64 * 65 * @var array 66 */ 67 static private $cache = array( 68 'parseMethod' => array(), 69 'getActiveRecordMethod' => array(), 70 'objectify' => array() 71 ); 72 73 /** 62 74 * Custom mappings for class <-> table 63 75 * … … 159 171 static public function callHookCallbacks($object, $hook, &$values, &$old_values, &$related_records, &$cache, &$parameter=NULL) 160 172 { 161 $class = self::getClass($object);173 $class = get_class($object); 162 174 163 175 if (empty(self::$hook_callbacks[$class][$hook]) && empty(self::$hook_callbacks['*'][$hook])) { … … 205 217 static public function callReflectCallbacks($object, &$signatures, $include_doc_comments) 206 218 { 207 $class = self::getClass($object);219 $class = get_class($object); 208 220 209 221 if (!isset(self::$reflect_callbacks[$class]) && !isset(self::$reflect_callbacks['*'])) { … … 242 254 * @internal 243 255 * 244 * @param mixed $class The name of the class, or an instance of it256 * @param string $class The name of the class 245 257 * @param string $hook The hook to check 246 258 * @param array $callback The specific callback to check for … … 249 261 static public function checkHookCallback($class, $hook, $callback=NULL) 250 262 { 251 $class = self::getClass($class);252 253 263 if (empty(self::$hook_callbacks[$class][$hook]) && empty(self::$hook_callbacks['*'][$hook])) { 254 264 return FALSE; … … 360 370 * @internal 361 371 * 362 * @param mixed $class The name of the class, or an instance of it372 * @param string $class The name of the class 363 373 * @param string $method The method to get the callback for 364 374 * @return string|null The callback for the method or `NULL` if none exists - see method description for details … … 366 376 static public function getActiveRecordMethod($class, $method) 367 377 { 368 $class = self::getClass($class); 378 // This caches method lookups, providing a significant performance 379 // boost to pages with lots of method calls that get passed to 380 // fActiveRecord::__call() 381 if (isset(self::$cache['getActiveRecordMethod'][$class . '::' . $method])) { 382 return (!$method = self::$cache['getActiveRecordMethod'][$class . '::' . $method]) ? NULL : $method; 383 } 384 385 $callback = NULL; 369 386 370 387 if (isset(self::$active_record_method_callbacks[$class][$method])) { 371 return self::$active_record_method_callbacks[$class][$method]; 372 } 373 374 if (isset(self::$active_record_method_callbacks['*'][$method])) { 375 return self::$active_record_method_callbacks['*'][$method]; 376 } 377 378 if (preg_match('#[A-Z0-9]#', $method)) { 388 $callback = self::$active_record_method_callbacks[$class][$method]; 389 390 } elseif (isset(self::$active_record_method_callbacks['*'][$method])) { 391 $callback = self::$active_record_method_callbacks['*'][$method]; 392 393 } elseif (preg_match('#[A-Z0-9]#', $method)) { 379 394 list($action, $subject) = self::parseMethod($method); 380 395 if (isset(self::$active_record_method_callbacks[$class][$action . '*'])) { 381 returnself::$active_record_method_callbacks[$class][$action . '*'];396 $callback = self::$active_record_method_callbacks[$class][$action . '*']; 382 397 } 383 398 } 384 399 385 return NULL; 400 self::$cache['getActiveRecordMethod'][$class . '::' . $method] = ($callback === NULL) ? FALSE : $callback; 401 return $callback; 386 402 } 387 403 … … 410 426 * @internal 411 427 * 412 * @param mixed $class The class name or instance of the classthe column is part of428 * @param string $class The class name the column is part of 413 429 * @param string $column The database column 414 430 * @return string The column name for the column specified … … 416 432 static public function getColumnName($class, $column) 417 433 { 418 $class = self::getClass($class);419 420 434 if (!isset(self::$column_names[$class])) { 421 435 self::$column_names[$class] = array(); … … 438 452 * @internal 439 453 * 440 * @param mixed $class The class name or instance of the classto get the record name of454 * @param string $class The class name to get the record name of 441 455 * @return string The record name for the class specified 442 456 */ 443 457 static public function getRecordName($class) 444 458 { 445 $class = self::getClass($class);446 447 459 if (!isset(self::$record_names[$class])) { 448 460 self::$record_names[$class] = fGrammar::humanize($class); … … 496 508 static public function objectify($class, $column, $value) 497 509 { 498 $class = self::getClass($class); 510 // This short-circuits computation for already checked columns, providing 511 // a nice little performance boost to pages with lots of records 512 if (isset(self::$cache['objectify'][$class . '::' . $column])) { 513 return $value; 514 } 499 515 500 516 if (!empty(self::$objectify_callbacks[$class][$column])) { … … 520 536 // Validation exception results in the raw value being saved 521 537 } 538 539 } else { 540 self::$cache['objectify'][$class . '::' . $column] = TRUE; 522 541 } 523 542 … … 576 595 static public function parseMethod($method) 577 596 { 597 if (isset(self::$cache['parseMethod'][$method])) { 598 return self::$cache['parseMethod'][$method]; 599 } 600 578 601 if (!preg_match('#^([a-z]+)(.*)$#D', $method, $matches)) { 579 602 throw new fProgrammerException( … … 582 605 ); 583 606 } 584 return array($matches[1], fGrammar::underscorize($matches[2])); 607 self::$cache['parseMethod'][$method] = array($matches[1], fGrammar::underscorize($matches[2])); 608 return self::$cache['parseMethod'][$method]; 585 609 } 586 610 … … 617 641 618 642 self::$active_record_method_callbacks[$class][$method] = $callback; 643 644 self::$cache['getActiveRecordMethod'] = array(); 619 645 } 620 646 … … 733 759 734 760 self::$objectify_callbacks[$class][$column] = $callback; 761 762 self::$cache['objectify'] = array(); 735 763 } 736 764 … … 849 877 * @internal 850 878 * 851 * @param mixed $class The class name or instance of the class the column is part of879 * @param string $class The class the column is part of 852 880 * @param string $column The database column 853 881 * @param mixed $value The value to copy/clone … … 856 884 static public function replicate($class, $column, $value) 857 885 { 858 $class = self::getClass($class);859 860 886 if (!empty(self::$replicate_callbacks[$class][$column])) { 861 887 return call_user_func(self::$replicate_callbacks[$class][$column], $class, $column, $value); … … 879 905 static public function reset() 880 906 { 907 self::$active_record_method_callbacks = array(); 908 self::$cache = array( 909 'parseMethod' => array(), 910 'getActiveRecordMethod' => array(), 911 'objectify' => array() 912 ); 881 913 self::$class_table_map = array(); 882 self::$active_record_method_callbacks = array();883 914 self::$column_names = array(); 884 915 self::$hook_callbacks = array(); … … 928 959 static public function tablize($class) 929 960 { 930 $class = self::getClass($class);931 932 961 if (!isset(self::$class_table_map[$class])) { 933 962 self::$class_table_map[$class] = fGrammar::underscorize(fGrammar::pluralize($class)); fORMColumn.php
r598 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fORMColumn 11 11 * 12 * @version 1.0.0b3 12 * @version 1.0.0b4 13 * @changes 1.0.0b4 Updated code for new fORM API [wb, 2009-06-15] 13 14 * @changes 1.0.0b3 Updated code to use new fValidationException::formatField() method [wb, 2009-06-04] 14 15 * @changes 1.0.0b2 Fixed a bug with objectifying number columns [wb, 2008-11-24] … … 331 332 list ($action, $column) = fORM::parseMethod($method_name); 332 333 333 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($object), $column); 334 $class = get_class($object); 335 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($class), $column); 334 336 $value = $values[$column]; 335 337 … … 365 367 list ($action, $column) = fORM::parseMethod($method_name); 366 368 367 $class = fORM::getClass($object);369 $class = get_class($object); 368 370 $table = fORM::tablize($class); 369 371 … … 540 542 list ($action, $column) = fORM::parseMethod($method_name); 541 543 542 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($object), $column); 544 $class = get_class($object); 545 $column_info = fORMSchema::retrieve()->getColumnInfo(fORM::tablize($class), $column); 543 546 $value = $values[$column]; 544 547 … … 594 597 595 598 if (isset(self::$number_columns[$class])) { 599 600 $table = fORM::tablize($class); 601 596 602 foreach(self::$number_columns[$class] as $column => $enabled) { 597 603 $camelized_column = fGrammar::camelize($column, TRUE); 598 $type = fORMSchema::retrieve()->getColumnInfo( fORM::tablize($class), $column, 'type');604 $type = fORMSchema::retrieve()->getColumnInfo($table, $column, 'type'); 599 605 600 606 // Get and set methods fORMFile.php
r600 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fORMFile 11 11 * 12 * @version 1.0.0b12 12 * @version 1.0.0b13 13 * @changes 1.0.0b13 Updated code for new fORM API [wb, 2009-06-15] 13 14 * @changes 1.0.0b12 Changed replacement values in preg_replace() calls to be properly escaped [wb, 2009-06-11] 14 15 * @changes 1.0.0b11 Updated code to use new fValidationException::formatField() method [wb, 2009-06-04] … … 744 745 list ($action, $column) = fORM::parseMethod($method_name); 745 746 746 $class = fORM::getClass($object);747 $class = get_class($object); 747 748 748 749 self::processImage($class, $column, $values[$column]); fORMOrdering.php
r602 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fORMOrdering 11 11 * 12 * @version 1.0.0b5 12 * @version 1.0.0b6 13 * @changes 1.0.0b6 Updated code for new fORM API [wb, 2009-06-15] 13 14 * @changes 1.0.0b5 Updated class to automatically correct ordering values that are too high [wb, 2009-06-14] 14 15 * @changes 1.0.0b4 Updated code to use new fValidationException::formatField() method [wb, 2009-06-04] … … 561 562 static public function validate($object, &$values, &$old_values, &$related_records, &$cache, &$validation_messages) 562 563 { 563 $class = fORM::getClass($object);564 $class = get_class($object); 564 565 $table = fORM::tablize($class); 565 566 fORMRelated.php
r598 r603 Hide Line Numbers 13 13 * @link http://flourishlib.com/fORMRelated 14 14 * 15 * @version 1.0.0b6 15 * @version 1.0.0b7 16 * @changes 1.0.0b7 Updated code for new fORM API, fixed API documentation bugs [wb, 2009-06-15] 16 17 * @changes 1.0.0b6 Updated code to use new fValidationException::formatField() method [wb, 2009-06-04] 17 18 * @changes 1.0.0b5 Added ::getPrimaryKeys() and ::setPrimaryKeys(), renamed ::setRecords() to ::setRecordSet() and ::tallyRecords() to ::setCount() [wb, 2009-06-02] … … 67 68 * @internal 68 69 * 69 * @param mixed $class The class name or instance of the class to get the related values for70 * @param string $class The class to get the related values for 70 71 * @param array &$related_records The related records existing for the fActiveRecord class 71 72 * @param string $related_class The class we are associating with the current record … … 111 112 * @internal 112 113 * 113 * @param mixed $class The class name or instance of the class to get the related values for114 * @param string $class The class to get the related values for 114 115 * @param array &$values The values for the fActiveRecord class 115 116 * @param array &$related_records The related records existing for the fActiveRecord class … … 186 187 * @internal 187 188 * 188 * @param mixed $class The class name or instance of the class to get the related values for189 * @param string $class The class to get the related values for 189 190 * @param array &$values The values for the fActiveRecord class 190 191 * @param array &$related_records The related records existing for the fActiveRecord class … … 242 243 * @internal 243 244 * 244 * @param mixed $class The class name or instance of the class to get the related valuesfor245 * @param string $class The class to create the related record for 245 246 * @param array $values The values existing in the fActiveRecord class 246 247 * @param string $related_class The related class name … … 250 251 static public function createRecord($class, $values, $related_class, $route=NULL) 251 252 { 252 $table = fORM::tablize($class); 253 253 $table = fORM::tablize($class); 254 254 $related_table = fORM::tablize($related_class); 255 255 … … 265 265 * @internal 266 266 * 267 * @param mixed $class The class name or instance of the main class267 * @param string $class The class name of the main class 268 268 * @param string $related_class The related class being filtered for 269 269 * @param string $route The route to the related table … … 300 300 * @internal 301 301 * 302 * @param mixed $class The class name or instance of the class to get the related values for302 * @param string $class The class to associate the related records to 303 303 * @param array &$related_records The related records existing for the fActiveRecord class 304 304 * @param string $related_class The class we are associating with the current record … … 331 331 * @internal 332 332 * 333 * @param mixed $class The class name or instance of the class this ordering rule applies to333 * @param string $class The class to get the order bys for 334 334 * @param string $related_class The related class the ordering rules apply to 335 335 * @param string $route The route to the related table, should be a column name in the current table or a join table name … … 356 356 * @internal 357 357 * 358 * @param mixed $class The class name or instance of the class to get the related values for358 * @param string $class The class to get the related primary keys for 359 359 * @param array &$values The values for the fActiveRecord class 360 360 * @param array &$related_records The related records existing for the fActiveRecord class … … 448 448 * @internal 449 449 * 450 * @param mixed $class The class name or instance of the class to get the related class name for451 * @param mixed $related_class The related class/class nameto get the record name of450 * @param string $class The class to get the related class name for 451 * @param string $related_class The related class to get the record name of 452 452 * @return string The record name for the related class specified 453 453 */ 454 454 static public function getRelatedRecordName($class, $related_class, $route=NULL) 455 455 { 456 $table = fORM::tablize($class); 457 458 $related_class = fORM::getClass($related_class); 456 $table = fORM::tablize($class); 459 457 $related_table = fORM::tablize($related_class); 460 458 … … 476 474 * @internal 477 475 * 478 * @param mixed $class The class name or instance of the class to get the related values for476 * @param string $class The class to get link the related records to 479 477 * @param array &$related_records The related records existing for the fActiveRecord class 480 478 * @param string $related_class The related class to populate … … 551 549 static public function overrideRelatedRecordName($class, $related_class, $record_name, $route=NULL) 552 550 { 553 $ table = fORM::tablize($class);554 551 $class = fORM::getClass($class); 552 $table = fORM::tablize($class); 555 553 $related_class = fORM::getClass($related_class); 556 554 $related_table = fORM::tablize($related_class); … … 575 573 * @internal 576 574 * 577 * @param mixed $class The class name or instance of the class to get the related values for575 * @param string $class The class to populate the related records of 578 576 * @param array &$related_records The related records existing for the fActiveRecord class 579 577 * @param string $related_class The related class to populate … … 583 581 static public function populateRecords($class, &$related_records, $related_class, $route=NULL) 584 582 { 583 $table = fORM::tablize($class); 585 584 $related_table = fORM::tablize($related_class); 586 585 $pk_columns = fORMSchema::retrieve()->getKeys($related_table, 'primary'); … … 590 589 591 590 $first_pk_column = NULL; 592 $relationships = fORMSchema::getRoutes($related_table, fORM::tablize($class), '*-to-one');591 $relationships = fORMSchema::getRoutes($related_table, $table, '*-to-one'); 593 592 foreach ($pk_columns as $pk_column) { 594 593 foreach ($relationships as $relationship) { … … 652 651 * @internal 653 652 * 654 * @param mixed $class The class name or instance of the class this ordering rule applies to653 * @param string $class The class to reflect the related record methods for 655 654 * @param array &$signatures The associative array of `{method_name} => {signature}` 656 655 * @param boolean $include_doc_comments If the doc block comments for each method should be included … … 882 881 static public function setOrderBys($class, $related_class, $order_bys, $route=NULL) 883 882 { 883 $class = fORM::getClass($class); 884 884 $table = fORM::tablize($class); 885 885 $related_table = fORM::tablize($related_class); … … 904 904 * @internal 905 905 * 906 * @param mixed $class The class name or instance of the class to get the related valuesfor906 * @param string $class The class to set the related records count for 907 907 * @param array &$values The values for the fActiveRecord class 908 908 * @param array &$related_records The related records existing for the fActiveRecord class … … 942 942 * @internal 943 943 * 944 * @param mixed $class The class name or instance of the class to get the related values for944 * @param string $class The class to set the related primary keys for 945 945 * @param array &$related_records The related records existing for the fActiveRecord class 946 946 * @param string $related_class The class we are setting the records for … … 975 975 * @internal 976 976 * 977 * @param mixed $class The class name or instance of the class to get the related values for977 * @param string $class The class to set the related records for 978 978 * @param array &$related_records The related records existing for the fActiveRecord class 979 979 * @param string $related_class The class we are associating with the current record … … 1008 1008 * @internal 1009 1009 * 1010 * @param mixed $class The class name or instance of the class to store the related records for1011 * @param array &$values The current values for the main record being stored1012 * @param array &$related_records The related records array1010 * @param string $class The class to store the related records for 1011 * @param array &$values The current values for the main record being stored 1012 * @param array &$related_records The related records array 1013 1013 * @return void 1014 1014 */ … … 1156 1156 * @internal 1157 1157 * 1158 * @param mixed $class The class name or instance of the class to validate the related records for1159 * @param array &$related_records The related records array1158 * @param string $class The class to validate the related records for 1159 * @param array &$related_records The related records array 1160 1160 * @return void 1161 1161 */ 1162 1162 static public function validate($class, &$related_records) 1163 1163 { 1164 $class = fORM::getClass($class);1165 1164 $table = fORM::tablize($class); 1166 1165 … … 1196 1195 * @internal 1197 1196 * 1198 * @param mixed $class The class name or instance of the class these records are related to1197 * @param string $class The class to validate the related records for 1199 1198 * @param string $related_class The name of the class for this record set 1200 1199 * @param string $route The route between the table and related table … … 1254 1253 * @internal 1255 1254 * 1256 * @param mixed $class The class name or instance of the class these records are related to1255 * @param string $class The class to validate the related records for 1257 1256 * @param string $related_class The name of the class for this record set 1258 1257 * @param string $route The route between the table and related table fORMSchema.php
r562 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fORMSchema 11 11 * 12 * @version 1.0.0b2 12 * @version 1.0.0b3 13 * @changes 1.0.0b3 Added routes caching for performance [wb, 2009-06-15] 13 14 * @changes 1.0.0b2 Backwards Compatiblity Break - removed ::enableSmartCaching(), fORM::enableSchemaCaching() now provides equivalent functionality [wb, 2009-05-04] 14 15 * @changes 1.0.0b The initial implementation [wb, 2007-06-14] … … 27 28 28 29 /** 30 * A cache for computed information 31 * 32 * @var array 33 */ 34 static private $cache = array( 35 'getRoutes' => array() 36 ); 37 38 39 /** 29 40 * The schema object to use for all ORM functionality 30 41 * … … 204 215 static public function getRoutes($table, $related_table, $relationship_type=NULL) 205 216 { 217 $key = $table . '::' . $related_table . '::' . $relationship_type; 218 if (isset(self::$cache['getRoutes'][$key])) { 219 return self::$cache['getRoutes'][$key]; 220 } 221 206 222 $valid_relationship_types = array( 207 223 NULL, … … 249 265 } 250 266 267 self::$cache['getRoutes'][$key] = $routes; 268 251 269 return $routes; 252 270 } fORMValidation.php
r598 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fORMValidation 11 11 * 12 * @version 1.0.0b8 12 * @version 1.0.0b9 13 * @changes 1.0.0b9 Updated code for new fORM API [wb, 2009-06-15] 13 14 * @changes 1.0.0b8 Updated code to use new fValidationException::formatField() method [wb, 2009-06-04] 14 15 * @changes 1.0.0b7 Updated ::validateRelated() to use new fORMRelated::validate() method and ::checkRelatedOneOrMoreRule() to use new `$related_records` structure [wb, 2009-06-02] … … 230 231 static private function checkAgainstSchema($object, $column, &$values, &$old_values) 231 232 { 232 $class = fORM::getClass($object);233 $class = get_class($object); 233 234 $table = fORM::tablize($class); 234 235 … … 282 283 * Validates against a conditional validation rule 283 284 * 284 * @param mixed $class The class name or instance of the class this validation rule applies to285 * @param string $class The class this validation rule applies to 285 286 * @param array &$values An associative array of all values for the record 286 287 * @param string $main_column The column to check for a value … … 316 317 * Validates a value against the database data type 317 318 * 318 * @param mixed $class The class name or instance of the class the column is part of319 * @param string $class The class the column is part of 319 320 * @param string $column The column to check 320 321 * @param mixed $value The value to check … … 387 388 * Validates values against foreign key constraints 388 389 * 389 * @param mixed $class The class name or instance of the class to check the foreign keys for390 * @param string $class The class to check the foreign keys for 390 391 * @param string $column The column to check 391 392 * @param array &$values The values to check … … 426 427 * Validates against a one-or-more validation rule 427 428 * 428 * @param mixed $class The class name or instance of the class the columns are part of429 * @param string $class The class the columns are part of 429 430 * @param array &$values An associative array of all values for the record 430 431 * @param array $columns The columns to check … … 458 459 * Validates against an only-one validation rule 459 460 * 460 * @param mixed $class The class name or instance of the class the columns are part of461 * @param string $class The class the columns are part of 461 462 * @param array &$values An associative array of all values for the record 462 463 * @param array $columns The columns to check … … 504 505 static private function checkPrimaryKeys($object, &$values, &$old_values) 505 506 { 506 $class = fORM::getClass($object);507 $class = get_class($object); 507 508 $table = fORM::tablize($class); 508 509 … … 570 571 * Validates against a *-to-many one or more validation rule 571 572 * 572 * @param mixed $class The class name or instance of the class we are checking573 * @param string $class The class we are checking 573 574 * @param array &$related_records The related records array to check 574 575 * @param string $related_class The name of the related class … … 604 605 static private function checkUniqueConstraints($object, $column, &$values, &$old_values) 605 606 { 606 $class = fORM::getClass($object);607 $class = get_class($object); 607 608 $table = fORM::tablize($class); 608 609 … … 700 701 * @internal 701 702 * 702 * @param mixed $class The class name or an instance of the class to initilize the arrays for703 * @param string $class The class to initilize the arrays for 703 704 * @return void 704 705 */ … … 717 718 * @internal 718 719 * 719 * @param mixed$class The class to check720 * @param string $class The class to check 720 721 * @param string $column The column to check 721 722 * @return boolean If the column is set to be case insensitive … … 723 724 static private function isCaseInsensitive($class, $column) 724 725 { 725 if (!isset(self::$case_insensitive_columns[$class][$column])) { 726 return FALSE; 727 } 728 return TRUE; 726 return isset(self::$case_insensitive_columns[$class][$column]); 729 727 } 730 728 … … 735 733 * @internal 736 734 * 737 * @param mixed $class The class name or an instance of the class to reorder messages for738 * @param array &$validation_messages An array of one validation message per value735 * @param string $class The class to reorder messages for 736 * @param array &$validation_messages An array of one validation message per value 739 737 * @return void 740 738 */ 741 739 static public function reorderMessages($class, &$validation_messages) 742 740 { 743 $class = fORM::getClass($class);744 745 741 if (!isset(self::$message_orders[$class])) { 746 742 return; … … 882 878 static public function validate($object, $values, $old_values) 883 879 { 884 $class = fORM::getClass($object);880 $class = get_class($object); 885 881 $table = fORM::tablize($class); 886 882 … … 932 928 * @internal 933 929 * 934 * @param mixed $class The class name or instance of the class to validate935 * @param array &$related_records The related records to validate930 * @param string $class The class to validate 931 * @param array &$related_records The related records to validate 936 932 * @return array An array of validation messages 937 933 */ 938 934 static public function validateRelated($class, &$related_records) 939 935 { 940 $class = fORM::getClass($class);941 936 $table = fORM::tablize($class); 942 937 fSchema.php
r597 r603 Hide Line Numbers 10 10 * @link http://flourishlib.com/fSchema 11 11 * 12 * @version 1.0.0b19 12 * @version 1.0.0b20 13 * @changes 1.0.0b20 Add caching of merged info, improved performance of ::getColumnInfo() [wb, 2009-06-15] 13 14 * @changes 1.0.0b19 Fixed a couple of bugs with ::setKeysOverride() [wb, 2009-06-04] 14 15 * @changes 1.0.0b18 Added missing support for MySQL mediumint columns [wb, 2009-05-18] … … 176 177 $this->cache->delete($prefix . 'databases'); 177 178 $this->cache->delete($prefix . 'keys'); 179 $this->cache->delete($prefix . 'merged_column_info'); 180 $this->cache->delete($prefix . 'merged_keys'); 181 $this->cache->delete($prefix . 'relationships'); 178 182 $this->cache->delete($prefix . 'tables'); 179 183 } … … 192 196 193 197 $prefix = $this->makeCachePrefix(); 194 $this->column_info = $this->cache->get($prefix . 'column_info', array()); 195 $this->databases = $this->cache->get($prefix . 'databases', NULL); 196 $this->keys = $this->cache->get($prefix . 'keys', array()); 197 $this->tables = $this->cache->get($prefix . 'tables', NULL); 198 $this->column_info = $this->cache->get($prefix . 'column_info', array()); 199 $this->databases = $this->cache->get($prefix . 'databases', NULL); 200 $this->keys = $this->cache->get($prefix . 'keys', array()); 201 202 if (!$this->column_info_override && !$this->keys_override) { 203 $this->merged_column_info = $this->cache->get($prefix . 'merged_column_info', array()); 204 $this->merged_keys = $this->cache->get($prefix . 'merged_keys', array()); 205 $this->relationships = $this->cache->get($prefix . 'relationships', array()); 206 } 207 208 $this->tables = $this->cache->get($prefix . 'tables', NULL); 198 209 } 199 210 … … 1714 1725 $this->findOneToManyRelationships($table); 1715 1726 } 1727 1728 if ($this->cache) { 1729 $this->cache->set($this->makeCachePrefix() . 'relationships', $this->relationships); 1730 } 1716 1731 } 1717 1732 … … 1772 1787 public function getColumnInfo($table, $column=NULL, $element=NULL) 1773 1788 { 1774 $valid_elements = array('type', 'not_null', 'default', 'valid_values', 'max_length', 'decimal_places', 'auto_increment'); 1775 if ($element && !in_array($element, $valid_elements)) { 1776 throw new fProgrammerException( 1777 'The element specified, %1$s, is invalid. Must be one of: %2$s.', 1778 $element, 1779 join(', ', $valid_elements) 1780 ); 1789 // Return the saved column info if possible 1790 if (!$column && isset($this->merged_column_info[$table])) { 1791 return $this->merged_column_info[$table]; 1792 } 1793 if ($column && isset($this->merged_column_info[$table][$column])) { 1794 if ($element !== NULL) { 1795 if (!isset($this->merged_column_info[$table][$column][$element]) && !array_key_exists($element, $this->merged_column_info[$table][$column])) { 1796 throw new fProgrammerException( 1797 'The element specified, %1$s, is invalid. Must be one of: %2$s.', 1798 $element, 1799 join(', ', array('type', 'not_null', 'default', 'valid_values', 'max_length', 'decimal_places', 'auto_increment')) 1800 ); 1801 } 1802 return $this->merged_column_info[$table][$column][$element]; 1803 } 1804 return $this->merged_column_info[$table][$column]; 1781 1805 } 1782 1806 … … 1786 1810 $table 1787 1811 ); 1788 }1789 1790 // Return the saved column info if possible1791 if (!$column && isset($this->merged_column_info[$table])) {1792 return $this->merged_column_info[$table];1793 }1794 if ($column && isset($this->merged_column_info[$table][$column])) {1795 if ($element !== NULL) {1796 return $this->merged_column_info[$table][$column][$element];1797 }1798 return $this->merged_column_info[$table][$column];1799 1812 } 1800 1813 … … 2218 2231 } 2219 2232 } 2233 2234 if ($this->cache) { 2235 $this->cache->set($this->makeCachePrefix() . 'merged_column_info', $this->merged_column_info); 2236 } 2220 2237 } 2221 2238 … … 2236 2253 } 2237 2254 $this->merged_keys[$table] = array_merge($this->merged_keys[$table], $info); 2255 } 2256 2257 if ($this->cache) { 2258 $this->cache->set($this->makeCachePrefix() . 'merged_keys', $this->merged_keys); 2238 2259 } 2239 2260
