Changeset 1245
- Timestamp:
- 02/07/09 17:49:17 (1 year ago)
- Files:
-
- trunk/lib/AkActiveRecord.php (modified) (10 diffs)
- trunk/lib/AkActiveRecord/AkDbAdapter.php (modified) (2 diffs)
- trunk/lib/AkActiveRecord/AkDbAdapters/AkMysqlDbAdapter.php (modified) (1 diff)
- trunk/lib/AkActiveRecord/AkDbSchemaCache.php (modified) (1 diff)
- trunk/lib/AkConfig.php (modified) (3 diffs)
- trunk/lib/AkInstaller.php (modified) (1 diff)
- trunk/test/unit/lib/AkActiveRecord/_AkActiveRecord_1.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/lib/AkActiveRecord.php
r1243 r1245 32 32 defined('AK_ACTIVE_RECORD_ENABLE_CALLBACK_SETTERS') ? null : define('AK_ACTIVE_RECORD_ENABLE_CALLBACK_SETTERS', AK_ACTIVE_RECORD_ENABLE_AUTOMATIC_SETTERS_AND_GETTERS); 33 33 defined('AK_ACTIVE_RECORD_ENABLE_CALLBACK_GETTERS') ? null : define('AK_ACTIVE_RECORD_ENABLE_CALLBACK_GETTERS', AK_ACTIVE_RECORD_ENABLE_AUTOMATIC_SETTERS_AND_GETTERS); 34 35 // Forces loading database schema on every call36 if(AK_DEV_MODE) {37 AkDbSchemaCache::doRefresh(true);38 } else if (AK_ENVIRONMENT == 'testing') {39 AkDbSchemaCache::doRefresh(true);40 define('AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA',true);41 }42 34 43 35 defined('AK_ACTIVE_RECORD_ENABLE_PERSISTENCE') ? null : define('AK_ACTIVE_RECORD_ENABLE_PERSISTENCE', AK_ENVIRONMENT != 'testing'); … … 2420 2412 function setTableName($table_name = null, $check_for_existence = AK_ACTIVE_RECORD_VALIDATE_TABLE_NAMES, $check_mode = false) 2421 2413 { 2422 !AK_TEST_MODE && $static_cached_tables = Ak::getStaticVar('available_tables');2423 2424 2414 if(empty($table_name)){ 2425 2415 $table_name = AkInflector::tableize($this->getModelName()); 2426 2416 } 2427 2417 if($check_for_existence){ 2428 if(!isset($available_tables) || $check_mode){ 2429 if(!isset($this->_db)){ 2430 $this->setConnection(); 2431 } 2432 if (!AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA || 2433 ($available_tables = AkDbSchemaCache::getAvailableTables()) === false) { 2434 if(!empty($static_cached_tables)){ 2435 $available_tables = $static_cached_tables; 2436 }else{ 2437 $available_tables = $this->_db->availableTables(); 2438 } 2439 if (AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA) { 2440 AkDbSchemaCache::setAvailableTables($available_tables); 2441 } 2442 !AK_TEST_MODE && Ak::setStaticVar('available_tables', $available_tables); 2443 } 2444 } 2445 if(!in_array($table_name,(array)$available_tables)){ 2418 !isset($this->_db) && $this->setConnection(); 2419 if(!$this->_db->tableExists($table_name, true)){ 2446 2420 if(!$check_mode){ 2447 2421 trigger_error(Ak::t('Unable to set "%table_name" table for the model "%model".'. … … 2542 2516 function _databaseTableInternals($table) 2543 2517 { 2544 if (! AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA || ($cache = AkDbSchemaCache::getDbTableInternals($table))===false) {2518 if (!$cache = AkDbSchemaCache::get('table_internals_for_'.$table)) { 2545 2519 $cache = $this->_db->getColumnDetails($table); 2546 if (AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA) { 2547 AkDbSchemaCache::setDbTableInternals($table,$cache); 2548 } 2520 AkDbSchemaCache::set('table_internals_for_'.$table, $cache); 2549 2521 } 2550 2522 return $cache; … … 2616 2588 $this->setConnection(); 2617 2589 } 2618 $this->_columnsSettings = $force_reload ? null : $this->_getPersistedTableColumnSettings(); 2619 2620 if(empty($this->_columnsSettings) || !AK_ACTIVE_RECORD_ENABLE_PERSISTENCE){ 2590 $this->_columnsSettings = ($force_reload ? null : $this->_getPersistedTableColumnSettings()); 2591 if(empty($this->_columnsSettings)){ 2621 2592 if(empty($this->_dataDictionary)){ 2622 2593 $this->_dataDictionary =& $this->_db->getDictionary(); … … 2626 2597 2627 2598 if( !isset($this->_avoidTableNameValidation) && 2628 !is_array($column_objects) &&2629 !$this->_runCurrentModelInstallerIfExists($column_objects)){2630 trigger_error(Ak::t('Ooops! Could not fetch details for the table %table_name.', array('%table_name'=>$this->getTableName())), E_USER_ERROR);2631 return false;2599 !is_array($column_objects) && 2600 !$this->_runCurrentModelInstallerIfExists($column_objects)){ 2601 trigger_error(Ak::t('Ooops! Could not fetch details for the table %table_name.', array('%table_name'=>$this->getTableName())), E_USER_ERROR); 2602 return false; 2632 2603 }elseif (empty($column_objects)){ 2633 2604 $this->_runCurrentModelInstallerIfExists($column_objects); … … 2638 2609 } 2639 2610 } 2640 if(!empty($this->_columnsSettings) && AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA){2611 if(!empty($this->_columnsSettings)){ 2641 2612 $this->_persistTableColumnSettings(); 2642 2613 } … … 2691 2662 } 2692 2663 2664 2693 2665 /** 2694 2666 * @access private 2695 2667 */ 2696 function _getColumnsSettings() 2697 { 2698 return AkDbSchemaCache::getColumnsSettings(); 2668 function _getModelColumnSettings() 2669 { 2670 return AkDbSchemaCache::get($this->getModelName().'_column_settings'); 2671 2699 2672 } 2700 2673 … … 2702 2675 * @access private 2703 2676 */ 2704 function _getModelColumnSettings() 2705 { 2706 return AkDbSchemaCache::getModelColumnSettings($this->getModelName()); 2707 2677 function _persistTableColumnSettings() 2678 { 2679 AkDbSchemaCache::set($this->getModelName().'_column_settings', $this->_columnsSettings); 2708 2680 } 2709 2681 … … 2711 2683 * @access private 2712 2684 */ 2713 function _persistTableColumnSettings()2714 {2715 AkDbSchemaCache::setModelColumnSettings($this->getModelName(), $this->_columnsSettings);2716 }2717 2718 /**2719 * @access private2720 */2721 2685 function _getPersistedTableColumnSettings() 2722 2686 { 2723 return AkDbSchemaCache::getModelColumnSettings($this->getModelName()); 2724 2687 return AkDbSchemaCache::get($this->getModelName().'_column_settings'); 2725 2688 } 2726 2689 … … 4516 4479 }elseif (is_array($this->act_as)){ 4517 4480 foreach ($this->act_as as $type=>$options){ 4518 if(is_numeric($type)){4519 $this->actsAs($options, array());4520 }else{4521 $this->actsAs($type, $options);4522 }4523 }4481 if(is_numeric($type)){ 4482 $this->actsAs($options, array()); 4483 }else{ 4484 $this->actsAs($type, $options); 4485 } 4486 } 4524 4487 } 4525 4488 } trunk/lib/AkActiveRecord/AkDbAdapter.php
r1185 r1245 374 374 * @return unknown 375 375 */ 376 function availableTables() 377 { 378 return $this->connection->MetaTables(); 379 } 376 function availableTables($force_lookup = false) 377 { 378 $available_tables = array(); 379 !AK_TEST_MODE && $available_tables = Ak::getStaticVar('available_tables'); 380 if(!$force_lookup && empty($available_tables)){ 381 if (($available_tables = AkDbSchemaCache::get('avaliable_tables')) === false) { 382 if(empty($available_tables)){ 383 $available_tables = $this->connection->MetaTables(); 384 } 385 AkDbSchemaCache::set('avaliable_tables', $available_tables); 386 !AK_TEST_MODE && Ak::setStaticVar('available_tables', $available_tables); 387 } 388 } 389 $available_tables = $force_lookup ? $this->connection->MetaTables() : $available_tables; 390 $force_lookup && !AK_TEST_MODE && Ak::setStaticVar('available_tables', $available_tables); 391 return $available_tables; 392 } 393 394 function tableExists($table_name) 395 { 396 // First try if cached 397 $available_tables = $this->availableTables(); 398 if(!in_array($table_name,(array)$available_tables)){ 399 // Force lookup and refresh cache 400 $available_tables = $this->availableTables(true); 401 return in_array($table_name,(array)$available_tables); 402 } 403 return true; 404 } 405 380 406 /** 381 407 * caching the meta info … … 384 410 * @return unknown 385 411 */ 412 386 413 function getColumnDetails($table_name) 387 414 { trunk/lib/AkActiveRecord/AkDbAdapters/AkMysqlDbAdapter.php
r1233 r1245 69 69 } 70 70 71 function availableTables()72 {73 return $this->selectValues('SHOW TABLES');74 }75 76 71 /* QUOTING */ 77 72 trunk/lib/AkActiveRecord/AkDbSchemaCache.php
r1196 r1245 1 1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 2 3 4 // +----------------------------------------------------------------------+ 5 // | Akelos Framework - http://www.akelos.org | 6 // +----------------------------------------------------------------------+ 7 // | Copyright (c) 2008-2009, Bermi Ferrer Martinez | 8 // | Released under the GNU Lesser General Public License, see LICENSE.txt| 9 // +----------------------------------------------------------------------+ 10 11 /** 12 * @package ActiveRecord 13 * @subpackage Base 14 * @component DbSchemaCache 15 * @author Arno Schneider 2008 16 * @author Bermi Ferrer 2009 17 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html> 18 */ 19 3 20 class AkDbSchemaCache 4 21 { 5 function doRefresh($set = null)22 function shouldRefresh($set = null) 6 23 { 7 static $refresh = false; 8 if ($set === false) { 9 $refresh = false; 10 } else if ($set === true) { 11 $refresh = true; 24 static $refresh; 25 if(!isset($refresh)){ 26 $refresh = !AK_ACTIVE_RECORD_CACHE_DATABASE_SCHEMA; 12 27 } 28 $refresh = is_null($set) ? $refresh : $set; 13 29 return $refresh; 14 30 } 15 function _generateCacheFileName($table, $environment = AK_ENVIRONMENT) 31 32 function getCacheFileName($environment = AK_ENVIRONMENT) 16 33 { 17 $namespace = Ak::sanitize_include($table, 'high'); 18 $cacheDir = AK_CONFIG_DIR; 34 return AkDbSchemaCache::getCacheDir().DS.$environment.'.serialized'; 35 } 36 37 function getCacheDir() 38 { 39 $cache_dir = AK_CONFIG_DIR; 19 40 if (defined('AK_CONFIG_CACHE_TMP') && AK_CONFIG_CACHE_TMP) { 20 $cache Dir = AK_TMP_DIR.DS.'ak_config';41 $cache_dir = AK_TMP_DIR.DS.'ak_config'; 21 42 } 22 $cacheFile = $cacheDir.DS.'cache'.DS.'activerecord'.DS.$environment.DS.$table.'.php'; 23 return $cacheFile; 43 return $cache_dir.DS.'cache'.DS.'activerecord'; 24 44 } 25 45 26 46 function clear($table, $environment = AK_ENVIRONMENT) 27 47 { 28 29 $modelName = AkInflector::singularize(AkInflector::classify($table)); 30 $cacheFileName = AkDbSchemaCache::_generateCacheFileName($modelName, $environment); 31 //echo "Cleaning cache: $cacheFileName\n"; 32 if (file_exists($cacheFileName)) { 33 @unlink($cacheFileName); 34 } 35 AkDbSchemaCache::_get($modelName,$environment,false,false); 36 $tableName = AkInflector::tableize($table); 37 $databaseInternalsFileName = AkDbSchemaCache::_generateCacheFileName('database_table_internals_'.$tableName); 38 //echo "Cleaning cache: $databaseInternalsFileName\n"; 39 if (file_exists($databaseInternalsFileName)) { 40 @unlink($databaseInternalsFileName); 41 } 42 43 AkDbSchemaCache::_get('database_table_internals_'.$tableName,$environment,false,false); 44 } 45 46 function clearAll($environment = AK_ENVIRONMENT) 47 { 48 $dummy = AkDbSchemaCache::_generateCacheFileName('dummy', $environment); 49 $dir = dirname($dummy); 50 $files = Ak::dir($dir); 51 foreach ($files as $file) { 52 if (is_file($dir.DS.$file)) { 53 @unlink($dir.DS.$file); 54 } 48 AkDbSchemaCache::_config($table, null, $environment, true); 49 AkDbSchemaCache::_config('database_table_internals_'.$table, null, $environment, true); 50 AkDbSchemaCache::_updateCacheFileAfterExecution($environment); 51 if(AK_LOG_EVENTS){ 52 $Logger =& Ak::getLogger(); 53 $Logger->message('Clearing database settings cache for '.$table); 55 54 } 56 55 } 57 56 58 function getAvailableTables($environment = AK_ENVIRONMENT)57 function clearAll() 59 58 { 60 return AkDbSchemaCache::_get('available_tables', $environment); 59 if(AK_LOG_EVENTS){ 60 $Logger =& Ak::getLogger(); 61 $Logger->message('Clearing all database settings from cache'); 62 } 63 Ak::directory_delete(AkDbSchemaCache::getCacheDir()); 61 64 } 62 65 63 function setAvailableTables($tables, $environment = AK_ENVIRONMENT)66 function get($key, $environment = AK_ENVIRONMENT) 64 67 { 65 AkDbSchemaCache::_set('available_tables',$tables, $environment); 66 } 67 function setModelColumnSettings($model, $config, $environment = AK_ENVIRONMENT) 68 { 69 return AkDbSchemaCache::_set($model, $config, $environment, false, true); 70 71 } 72 function setDbTableInternals($table, $internals, $environment = AK_ENVIRONMENT) 73 { 74 return AkDbSchemaCache::_set('database_table_internals_'.$table, $internals, $environment); 75 } 76 function getDbTableInternals($table, $environment = AK_ENVIRONMENT) 77 { 78 return AkDbSchemaCache::_get('database_table_internals_'.$table,$environment); 79 } 80 function getColumnsSettings($environment = AK_ENVIRONMENT) 81 { 82 return AkDbSchemaCache::_get(true,$environment); 83 84 } 85 function getModelColumnSettings($model, $environment = AK_ENVIRONMENT) 86 { 87 return AkDbSchemaCache::_get($model, $environment, false, null, true); 88 } 89 function &_get($type, $environment = AK_ENVIRONMENT, $uncached = false, $set = null, $var_export = false) 90 { 91 $false = false; 92 if (AkDbSchemaCache::doRefresh() && $set === null) return $false; 93 $null = null; 94 static $configs = array(); 95 if ($set !== null) { 96 if (!isset($configs[$environment])) { 97 $configs[$environment] = array(); 98 } 99 if ($set === false) { 100 unset($configs[$environment][$type]); 101 } else { 102 $configs[$environment][$type] = $set; 103 } 104 return $null; 105 } 106 107 if ($type === true) { 108 return isset($configs[$environment]) ? $configs[$environment] : array(); 109 } 110 if (!$uncached && isset($configs[$environment]) && isset($configs[$environment][$type])) { 111 return $configs[$environment][$type]; 112 } 113 if ($uncached || !($config = AkDbSchemaCache::_readCache($type, $environment, false, $var_export))) { 114 return $false; 115 } 116 if (!isset($configs[$environment])) { 117 $configs[$environment] = array($type=>$config); 118 } else { 119 $configs[$environment][$type] = $config; 120 } 121 return $configs[$environment][$type]; 68 return AkDbSchemaCache::_config($key, null, $environment, false); 122 69 } 123 70 124 function _readCache($table, $environment = AK_ENVIRONMENT, $force = false, $var_export = false)71 function set($key, $value, $environment = AK_ENVIRONMENT) 125 72 { 126 $cacheFileName = AkDbSchemaCache::_generateCacheFileName($table,$environment); 127 if (file_exists($cacheFileName)) { 128 if ($var_export === false) { 129 $config = unserialize(file_get_contents($cacheFileName)); 130 } else { 131 $config = include $cacheFileName; 132 } 133 } else { 134 $config = false; 135 } 136 return $config; 73 AkDbSchemaCache::_updateCacheFileAfterExecution($environment); 74 return AkDbSchemaCache::_config($key, $value, $environment, !is_null($value)); 137 75 } 138 76 139 function _ set($type, $config, $environment = AK_ENVIRONMENT, $force = false, $var_export = false)77 function _updateCacheFileAfterExecution($environment = null) 140 78 { 141 if ($var_export === false) { 142 $cache = serialize($config); 143 } else { 144 $cacheStr = var_export($config,true); 145 $cache = <<<EOF 146 <?php 147 \$cache = $cacheStr; 148 return \$cache; 79 static $called = false, $_environment; 80 if($called == false && !AkDbSchemaCache::shouldRefresh()){ 81 register_shutdown_function(array('AkDbSchemaCache','_updateCacheFileAfterExecution')); 82 $called = !empty($environment) ? $environment : AK_ENVIRONMENT; 83 }elseif(empty($environment)){ 84 $config = AkDbSchemaCache::_config(null, null, $called); 85 $file_name = AkDbSchemaCache::getCacheFileName($called); 86 if(AK_LOG_EVENTS){ 87 $Logger =& Ak::getLogger(); 88 $Logger->message('Updating database settings on '.$file_name); 89 } 90 /** 91 * @todo On PHP5 var_export requires objects that implement the __set_state magic method. 92 * As see on stangelanda at arrowquick dot benchmarks at comhttp://php.net/var_export 93 * serialize works faster without opcode caches. We should do our benchmarks with 94 * var_export VS serialize using APC once we fix the __set_state magic on phpAdoDB 95 */ 96 Ak::file_put_contents($file_name, serialize($config)); 97 } 98 } 99 100 function _config($key = null, $value = null, $environment = AK_ENVIRONMENT, $unset = false) 101 { 102 if(AkDbSchemaCache::shouldRefresh()){ 103 return false; 104 } 105 static $config; 106 if(!isset($config[$environment])){ 107 $file_name = AkDbSchemaCache::getCacheFileName($environment); 108 $config[$environment] = file_exists($file_name) ? unserialize(Ak::file_get_contents($file_name)) : array(); 109 if(AK_LOG_EVENTS){ 110 $Logger =& Ak::getLogger(); 111 $Logger->message('Loading cached database settings'); 112 } 113 } 114 if(!is_null($key)){ 115 if(!is_null($value)){ 116 $config[$environment][$key] = $value; 117 }elseif($unset){ 118 unset($config[$environment][$key]); 119 } 120 return isset($config[$environment][$key]) ? $config[$environment][$key] : false; 121 } 122 return $config[$environment]; 123 } 124 } 125 149 126 ?> 150 EOF;151 }152 $cacheFileName = AkDbSchemaCache::_generateCacheFileName($type,$environment);153 $cacheDir = dirname($cacheFileName);154 155 if (!file_exists($cacheDir)) {156 $oldumask = umask();157 umask(0);158 $res = @mkdir($cacheDir,0777,true);159 if (!$res) {160 trigger_error(Ak::t('Could not create config cache dir %dir',array('%dir'=>$cacheDir)),E_USER_ERROR);161 }162 umask($oldumask);163 }164 $fh = fopen($cacheFileName,'w+');165 if ($fh) {166 fputs($fh,$cache);167 fclose($fh);168 @chmod($cacheFileName,0777);169 } else {170 trigger_error(Ak::t('Could not create dbschema cache file %file',array('%file'=>$cacheFileName)),E_USER_ERROR);171 }172 AkDbSchemaCache::_get($type, $environment, false, $config);173 }174 175 }176 ?>trunk/lib/AkConfig.php
r1196 r1245 171 171 return $config; 172 172 } 173 173 174 function _writeCache($config, $namespace, $environment = AK_ENVIRONMENT, $force = false) 174 175 { … … 207 208 $this->_setCacheValidity($namespace,$environment); 208 209 } 210 209 211 function _generateConfigFileName($namespace,$environment = AK_ENVIRONMENT) 210 212 { … … 273 275 function _getConstant($name) 274 276 { 275 return defined($name[1]) ?constant($name[1]):'';277 return defined($name[1]) ? constant($name[1]) : ''; 276 278 } 277 279 trunk/lib/AkInstaller.php
r1223 r1245 89 89 $this->db =& $db_connection; 90 90 } 91 91 AkDbSchemaCache::clearAll(); 92 92 $this->data_dictionary =& $this->db->getDictionary(); 93 93 $this->available_tables = $this->getAvailableTables(); trunk/test/unit/lib/AkActiveRecord/_AkActiveRecord_1.php
r1185 r1245 57 57 $this->assertEqual($AkTestUser->getModelName(), 'AkTestUser'); 58 58 $this->assertEqual($AkTestUser->getTableName(), 'ak_test_users'); 59 $this->assertErrorPattern('/ak_test_user/', $AkTestUser->setTableName('ak_test_user'));59 $this->assertErrorPattern('/ak_test_user/', $AkTestUser->setTableName('ak_test_user')); 60 60 61 61 //$this->_createNewTestingModel('AkTestUnavailableDatabase'); … … 130 130 function Test_of_loadColumnsSettings() 131 131 { 132 AkDbSchemaCache::shouldRefresh(false); 132 133 $AkTestField = new AkTestField(); 133 134 $AkTestField->loadColumnsSettings(); 134 135 // Testing database settings cache on session (this might be changed in a future 135 AkDbSchemaCache::doRefresh(false); 136 $this->assertEqual($AkTestField->_columnsSettings,AkDbSchemaCache::getModelColumnSettings('AkTestField')); 137 AkDbSchemaCache::doRefresh(true); 136 $this->assertEqual($AkTestField->_columnsSettings, AkDbSchemaCache::get('AkTestField_column_settings')); 137 AkDbSchemaCache::shouldRefresh(true); 138 138 } 139 139 … … 569 569 } 570 570 571 function Test_of_getSerializedAttributes_and_setSerializeAttribute()572 {573 $User = new AkTestUser();574 $User->addCombinedAttributeConfiguration('name', "%s %s", 'first_name', 'last_name');575 $User->setSerializeAttribute('user_name');576 $User->setSerializeAttribute('name');577 $User->setSerializeAttribute('not_valid');578 $User->setSerializeAttribute('email','MimeEmail');579 $expected = array('user_name' => null, 'email' => 'MimeEmail');580 $this->assertEqual($expected, $User->getSerializedAttributes());581 582 }583 584 571 function Test_of_setAccessibleAttributes() 585 572 {
