Xataface 2.0
Xataface Application Framework
Dataface/ConfigTool.php
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Enumerations