![]() |
Xataface 2.0
Xataface Application Framework
|
00001 <?php 00002 /*------------------------------------------------------------------------------- 00003 * Xataface Web Application Framework 00004 * Copyright (C) 2005-2008 Web Lite Solutions Corp (shannah@sfu.ca) 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 *------------------------------------------------------------------------------- 00020 */ 00021 00031 require_once 'I18Nv2/I18Nv2.php'; 00032 00033 class Dataface_ConfigTool { 00034 00035 var $configTypes = array('actions','fields','relationships','valuelists','tables','lang','metadata'); 00036 var $rawConfig = array(); 00037 var $config = array(); 00038 var $configLoaded = false; 00039 var $iniLoaded = array(); 00040 var $configTableName = 'dataface__config'; 00041 00042 function Dataface_ConfigTool(){ 00043 $this->apc_load(); 00044 register_shutdown_function(array(&$this, 'apc_save')); 00045 } 00046 00050 var $nameLookup = array('actions'=>array(), 'fields'=>array(), 'table'=>array(), 'relationships'=>array(), 'valuelists'=>array(),'lang'=>array()); 00051 00052 public static function &getInstance(){ 00053 static $instance = 0; 00054 if (!$instance ){ 00055 $instance = new Dataface_ConfigTool(); 00056 } 00057 return $instance; 00058 } 00059 00066 function &loadConfig($type=null, $table=null){ 00067 $out =& $this->loadConfigFromINI($type, $table); 00068 return $out; 00069 } 00070 00071 00079 function &loadConfigFromINI($type=null, $tablename='__global__'){ 00080 if ( !isset($tablename) ) $tablename = '__global__'; 00081 $app =& Dataface_Application::getInstance(); 00082 if ( $type == 'lang' ){ 00083 if ( isset($this->config[$type][$app->_conf['lang']][$tablename]) ){ 00084 return $this->config[$type][$app->_conf['lang']][$tablename]; 00085 } 00086 } else { 00087 if ( isset( $this->config[$type][$tablename] ) ){ 00088 return $this->config[$type][$tablename]; 00089 } 00090 } 00091 $app =& Dataface_Application::getInstance(); 00092 $paths = array(); 00093 $lpaths = array(); 00094 if ( $type === 'lang' ){ 00095 00096 if ( $tablename !== '__global__' ){ 00097 if ( !class_exists('Dataface_Table') ) import('Dataface/Table.php'); 00098 $lpaths[] = Dataface_Table::getBasePath($tablename).'/tables/'.basename($tablename).'/lang/'.basename($app->_conf['lang']).'.ini'; 00099 00100 } else { 00101 $paths[] = DATAFACE_PATH.'/lang/'.basename($app->_conf['lang']).'.ini'; 00102 $lpaths[] = DATAFACE_SITE_PATH.'/lang/'.basename($app->_conf['lang']).'.ini'; 00103 } 00104 00105 } else if ( $tablename !== '__global__' ){ 00106 //$paths = array(DATAFACE_SITE_PATH.'/tables/'.$tablename.'/'.$type.'.ini'); 00107 $paths[] = DATAFACE_PATH.'/'.basename($type).'.ini'; 00108 $lpaths[] = DATAFACE_SITE_PATH.'/'.basename($type).'.ini'; 00109 $lpaths[] = Dataface_Table::getBasePath($tablename).'/tables/'.basename($tablename).'/'.basename($type).'.ini'; 00110 00111 } else { 00112 00113 $paths[] = DATAFACE_PATH.'/'.basename($type).'.ini'; 00114 $lpaths[] = DATAFACE_SITE_PATH.'/'.basename($type).'.ini'; 00115 } 00116 00117 // Add the ability to override settings in a module. 00118 // Added Feb. 28, 2007 by Steve Hannah for version 0.6.14 00119 if ( isset($app->_conf['_modules']) and count($app->_conf['_modules']) > 0 ){ 00120 foreach ( $app->_conf['_modules'] as $classname=>$path ){ 00121 $modpath = explode('_',$classname); 00122 $modname = $modpath[count($modpath)-1]; 00123 if ( $type == 'lang' ){ 00124 $paths[] = DATAFACE_SITE_PATH.'/modules/'.basename($modname).'/lang/'.basename($app->_conf['lang']).'.ini'; 00125 $paths[] = DATAFACE_PATH.'/modules/'.basename($modname).'/lang/'.basename($app->_conf['lang']).'.ini'; 00126 } else { 00127 $paths[] = DATAFACE_SITE_PATH.'/modules/'.basename($modname).'/'.basename($type).'.ini'; 00128 $paths[] = DATAFACE_PATH.'/modules/'.basename($modname).'/'.basename($type).'.ini'; 00129 } 00130 } 00131 } 00132 00133 // Add the ability to override settings in the database. 00134 // Added Feb. 27, 2007 by Steve Hannah for version 0.6.14 00135 if ( @$app->_conf['enable_db_config'] and $type != 'permissions'){ 00136 if ( $type == 'lang' ){ 00137 if ( isset($tablename) ){ 00138 $lpaths[] = 'db:tables/'.basename($tablename).'/lang/'.basename($app->_conf['lang']); 00139 } else { 00140 $paths[] = 'db:lang/'.basename($app->_conf['lang']).'.ini'; 00141 } 00142 } else { 00143 if ( isset($tablename) ){ 00144 $paths[] = 'db:'.basename($type).'.ini'; 00145 $lpaths[] = 'db:tables/'.basename($tablename).'/'.basename($type).'.ini'; 00146 } else { 00147 $paths[] = 'db:'.basename($type).'.ini'; 00148 } 00149 } 00150 } 00151 00152 if ( !$tablename ){ 00153 $tablename = '__global__'; 00154 00155 } 00156 00157 $paths = array_merge($paths, $lpaths); 00158 //print_r($paths); 00159 //print_r($lpaths); 00160 if ( !isset( $this->config[$type][$tablename] ) ) $this->config[$type][$tablename] = array(); 00161 //import('Config.php'); 00162 00163 foreach ( $paths as $path ){ 00164 if ( !isset( $this->iniLoaded[$path] ) ){ 00165 $this->iniLoaded[$path] = true; 00166 00167 if ( is_readable($path) || strstr($path,'db:') == $path ){ 00168 00169 00170 $config = $this->parse_ini_file($path, true); 00171 00172 if ( isset( $config['charset'] ) and function_exists('iconv') ){ 00173 I18Nv2::recursiveIconv($config, $config['charset'], 'UTF-8'); 00174 } 00175 00176 00177 if ( isset($config['__extends__']) ){ 00178 $config = array_merge_recursive_unique($this->loadConfigFromINI($type, $config['__extends__']), $config); 00179 } 00180 00181 $this->rawConfig[$path] =& $config; 00182 00183 } else { 00184 $config = array(); 00185 $this->rawConfig[$path] =& $config; 00186 } 00187 } else { 00188 //echo "getting $path from raw config."; 00189 //echo "$path already loaded:".implode(',', array_keys($this->iniLoaded)); 00190 $config =& $this->rawConfig[$path]; 00191 } 00192 00193 00194 //echo "Conf for x".$path."x: "; 00195 if ( !$config ) $config = array(); 00196 00197 foreach ( array_keys($config) as $entry ){ 00198 if ( $type == 'lang'){ 00199 $this->config[$type][$app->_conf['lang']][$tablename][$entry] =& $config[$entry]; 00200 } else { 00201 $sep = null; 00202 if ( strpos($entry, '>') !== false ){ 00203 $sep = '>'; 00204 } 00205 if ( strpos($entry, ' extends ') !== false ){ 00206 $sep = ' extends '; 00207 } 00208 if ( $sep and is_array($config[$entry]) ){ 00209 list($newentry,$entryParents) = explode($sep, $entry); 00210 $entryParents = array_map('trim',explode(',', $entryParents)); 00211 $newentry = trim($newentry); 00212 $cout = array(); 00213 foreach ($entryParents as $entryParent){ 00214 if ( !isset($this->config[$type][$tablename][$entryParent]) ){ 00215 throw new Exception("Illegal extends. Parent not found: ".$entryParent." from rule: ".$entry." in ".$path); 00216 } 00217 $pconf =& $this->config[$type][$tablename][$entryParent]; 00218 if ( !is_array($pconf) ){ 00219 throw new Exception("Illegal extends. Parent is not a section. It is a scalar: ".$entryParent." from rule: ".$entry." in ".$path); 00220 00221 } 00222 foreach ($pconf as $pkey=>$pval){ 00223 $cout[$pkey] = $pval; 00224 } 00225 unset($pconf); 00226 00227 } 00228 $centry =& $config[$entry]; 00229 foreach ($centry as $ckey=>$cval){ 00230 $cout[$ckey] = $cval; 00231 } 00232 unset($centry); 00233 unset($this->config[$type][$tablename][$entry]); 00234 unset($this->config[$type][$tablename][$newentry]); 00235 $this->config[$type][$tablename][$newentry] =& $cout; 00236 unset($cout); 00237 00238 00239 //$this->config[$type][$tablename][trim($newentry)] = array_merge($this->config[$type][$tablename][trim($entryParent)],$config[$entry]); 00240 } else { 00241 $this->config[$type][$tablename][$entry] =& $config[$entry]; 00242 } 00243 00244 } 00245 } 00246 00247 unset($config); 00248 } 00249 if ( $type == 'lang' ){ 00250 return $this->config[$type][$app->_conf['lang']][$tablename]; 00251 } else { 00252 return $this->config[$type][$tablename]; 00253 } 00254 00255 } 00256 00257 function apc_save(){ 00258 if ( function_exists('apc_store') and defined('DATAFACE_USE_CACHE') and DATAFACE_USE_CACHE ){ 00259 $res = apc_store($this->apc_hash().'$config', $this->config); 00260 $res2 = apc_store($this->apc_hash().'$iniLoaded', $this->iniLoaded); 00261 00262 } 00263 } 00264 00265 function apc_load(){ 00266 if ( function_exists('apc_fetch') and defined('DATAFACE_USE_CACHE') and DATAFACE_USE_CACHE ){ 00267 $this->config = apc_fetch($this->apc_hash().'$config'); 00268 $this->iniLoaded = apc_fetch($this->apc_hash().'$iniLoaded'); 00269 } 00270 } 00271 00272 function apc_hash(){ 00273 $appname = basename(DATAFACE_SITE_PATH); 00274 return __FILE__.'-'.$appname; 00275 } 00276 00277 00278 00282 function loadAllConfigFromINI(){ 00283 $tables_path = DATAFACE_SITE_PATH.'/tables'; 00284 $dir = dir($tables_path); 00285 while ( false !== ( $entry = $dir->read() ) ){ 00286 if ( $entry === '.' || $entry === '..' ) continue; 00287 $full_path = $tables_path.'/'.$entry; 00288 if ( is_dir($full_path) ){ 00289 foreach ( $this->configTypes as $type ){ 00290 $this->loadConfigFromINI($type, $entry); 00291 } 00292 } 00293 } 00294 foreach ($this->configTypes as $type){ 00295 // load global properties. 00296 $this->loadConfigFromINI($type, null); 00297 } 00298 00299 } 00300 00301 function loadAllConfig(){ 00302 $app =& Dataface_Application::getInstance(); 00303 switch( strtolower($app->_conf['config_storage']) ){ 00304 case 'db': 00305 case 'sql': 00306 case 'database': 00307 $this->loadConfigFromDB(); 00308 break; 00309 case 'ini': 00310 $this->loadAllConfigFromINI(); 00311 break; 00312 00313 } 00314 00315 } 00316 00317 00318 00319 function parse_ini_file($path, $sections=false){ 00320 static $config = 0; 00321 if ( !is_array($config) ){ 00322 $config = array(); 00323 } 00324 00325 00326 00327 $app =& Dataface_Application::getInstance(); 00328 //echo "Checking for $path"; 00329 if ( strstr($path, 'db:') == $path ){ 00330 $path = substr($path, 3); 00331 if ( !is_array($config) ){ 00332 $config = array(); 00333 if ( class_exists('Dataface_AuthenticationTool') ){ 00334 $auth =& Dataface_AuthenticationTool::getInstance(); 00335 $username = $auth->getLoggedInUsername(); 00336 } else { 00337 $username = null; 00338 } 00339 00340 00341 $sql = $this->buildConfigQuery($path, $username, $app->_conf['lang']); 00342 $res = @mysql_query($sql, $app->db()); 00343 if (!$res ){ 00344 $this->createConfigTable(); 00345 $res = mysql_query($sql, $app->db()); 00346 } 00347 if ( !$res ){ 00348 return $config; 00349 } 00350 while ( $row = mysql_fetch_assoc($res) ){ 00351 if ( !$row['section'] ){ 00352 $config[$row['file']][$row['key']] = $row['value']; 00353 } else { 00354 $config[$row['file']][$row['section']][$row['key']] = $row['value']; 00355 } 00356 } 00357 @mysql_free_result($res); 00358 00359 00360 } 00361 00362 if ( !@$config[$path] ){ 00363 00364 return array(); 00365 } 00366 00367 return $config[$path]; 00368 00369 } else { 00370 if ( !(DATAFACE_EXTENSION_LOADED_APC && (filemtime($path) < apc_fetch($this->apc_hash().$path.'__mtime')) && ( $config[$path]=apc_fetch($this->apc_hash().$path) ) ) ){ 00371 00372 00373 //$config[$path] = parse_ini_file($path, $sections); 00374 $config[$path] = INIParser::parse_ini_file($path, $sections); 00375 if ( DATAFACE_EXTENSION_LOADED_APC ){ 00376 apc_store($this->apc_hash().$path, $config[$path]); 00377 apc_store($this->apc_hash().$path.'__mtime', time()); 00378 } 00379 } else { 00380 // 00381 } 00382 00383 00384 return $config[$path]; 00385 00386 } 00387 00388 } 00389 00390 function buildConfigQuery($path, $username, $lang, $where=null){ 00391 $sql = "select * from `".$this->configTableName."` where (`lang` IS NULL OR `lang` = '".$lang."') and ( `username` IS NULL"; 00392 if ( isset($username) ){ 00393 $sql .= " OR `username` = '".addslashes($username)."')"; 00394 } else { 00395 $sql .= ')'; 00396 } 00397 if ( isset($where) ) $sql .= ' and ('.$where.')'; 00398 00399 00400 $sql .= ' ORDER BY `priority`'; 00401 return $sql; 00402 } 00403 00404 00405 function createConfigTable(){ 00406 import('Dataface/ConfigTool/createConfigTable.function.php'); 00407 return Dataface_ConfigTool_createConfigTable(); 00408 } 00409 00410 function setConfigParam($file, $section, $key, $value, $username=null, $lang=null, $priority=5){ 00411 import('Dataface/ConfigTool/setConfigParam.function.php'); 00412 return Dataface_ConfigTool_setConfigParam($file, $section, $key, $value, $username, $lang, $priority); 00413 } 00414 00415 function clearConfigParam($file, $section, $key, $value, $username=null, $lang=null){ 00416 import('Dataface/ConfigTool/clearConfigParam.function.php'); 00417 return Dataface_ConfigTool_setConfigParam($file, $section, $key, $value, $username, $lang); 00418 } 00419 00420 } 00421 00422 00423 00424 class INIParser { 00425 private $keys = array(); 00426 private function replace_key($matches){ 00427 $this->keys[] = trim($matches[1]); 00428 return 'keys'.(count($this->keys)-1).'='; 00429 } 00430 00431 private function replace_section($matches){ 00432 $this->keys[] = trim($matches[1]); 00433 return '[keys'.(count($this->keys)-1).']'; 00434 } 00435 00436 private function return_key($matches){ 00437 $index = intval($matches[1]); 00438 if ( isset($this->keys[$index]) ){ 00439 return $this->keys[$index].'='; 00440 } else { 00441 return $matches[0]; 00442 } 00443 } 00444 00445 00446 private function refill_array($ini){ 00447 foreach ( $ini as $key=>$val){ 00448 if ( is_array($val) ){ 00449 00450 $val = $this->refill_array($val); 00451 00452 } else { 00453 $val = preg_replace_callback('/^keys(\d+)=/m', array($this, 'return_key'), $val); 00454 } 00455 $index = intval(substr($key, 4)); 00456 if ( isset($this->keys[$index]) ){ 00457 unset($ini[$key]); 00458 $ini[$this->keys[$index]] = $val; 00459 } else { 00460 $ini[$key] = $val; 00461 } 00462 } 00463 return $ini; 00464 } 00465 00466 00467 private function parse($file, $sections=false){ 00468 $this->keys = array(); 00469 $contents = file_get_contents($file); 00470 $contents = preg_replace_callback('/^ *\[([^\]]+)\]/m', array($this, 'replace_section'), $contents); 00471 00472 $contents = preg_replace_callback('/^([^\[=;"]+)(=)/m', array($this, 'replace_key'), $contents); 00473 //echo $contents; 00474 $ini = parse_ini_string($contents, $sections); 00475 return $this->refill_array($ini); 00476 } 00477 public static function parse_ini_file($file, $sections=false){ 00478 if ( version_compare(PHP_VERSION, '5.3.0') >= 0 and version_compare(PHP_VERSION, '5.3.1') <= 0 ){ 00479 $p = new INIParser(); 00480 return $p->parse($file, $sections); 00481 } else { 00482 return parse_ini_file($file, $sections); 00483 } 00484 } 00485 00486 }