MediaWiki  REL1_22
SiteConfiguration.php
Go to the documentation of this file.
00001 <?php
00117 class SiteConfiguration {
00118 
00122     public $suffixes = array();
00123 
00127     public $wikis = array();
00128 
00132     public $settings = array();
00133 
00137     public $localVHosts = array();
00138 
00143     public $fullLoadCallback = null;
00144 
00146     public $fullLoadDone = false;
00147 
00162     public $siteParamsCallback = null;
00163 
00168     protected $cfgCache = array();
00169 
00179     public function get( $settingName, $wiki, $suffix = null, $params = array(), $wikiTags = array() ) {
00180         $params = $this->mergeParams( $wiki, $suffix, $params, $wikiTags );
00181         return $this->getSetting( $settingName, $wiki, $params );
00182     }
00183 
00192     protected function getSetting( $settingName, $wiki, /*array*/ $params ) {
00193         $retval = null;
00194         if ( array_key_exists( $settingName, $this->settings ) ) {
00195             $thisSetting =& $this->settings[$settingName];
00196             do {
00197                 // Do individual wiki settings
00198                 if ( array_key_exists( $wiki, $thisSetting ) ) {
00199                     $retval = $thisSetting[$wiki];
00200                     break;
00201                 } elseif ( array_key_exists( "+$wiki", $thisSetting ) && is_array( $thisSetting["+$wiki"] ) ) {
00202                     $retval = $thisSetting["+$wiki"];
00203                 }
00204 
00205                 // Do tag settings
00206                 foreach ( $params['tags'] as $tag ) {
00207                     if ( array_key_exists( $tag, $thisSetting ) ) {
00208                         if ( isset( $retval ) && is_array( $retval ) && is_array( $thisSetting[$tag] ) ) {
00209                             $retval = self::arrayMerge( $retval, $thisSetting[$tag] );
00210                         } else {
00211                             $retval = $thisSetting[$tag];
00212                         }
00213                         break 2;
00214                     } elseif ( array_key_exists( "+$tag", $thisSetting ) && is_array( $thisSetting["+$tag"] ) ) {
00215                         if ( !isset( $retval ) ) {
00216                             $retval = array();
00217                         }
00218                         $retval = self::arrayMerge( $retval, $thisSetting["+$tag"] );
00219                     }
00220                 }
00221                 // Do suffix settings
00222                 $suffix = $params['suffix'];
00223                 if ( !is_null( $suffix ) ) {
00224                     if ( array_key_exists( $suffix, $thisSetting ) ) {
00225                         if ( isset( $retval ) && is_array( $retval ) && is_array( $thisSetting[$suffix] ) ) {
00226                             $retval = self::arrayMerge( $retval, $thisSetting[$suffix] );
00227                         } else {
00228                             $retval = $thisSetting[$suffix];
00229                         }
00230                         break;
00231                     } elseif ( array_key_exists( "+$suffix", $thisSetting ) && is_array( $thisSetting["+$suffix"] ) ) {
00232                         if ( !isset( $retval ) ) {
00233                             $retval = array();
00234                         }
00235                         $retval = self::arrayMerge( $retval, $thisSetting["+$suffix"] );
00236                     }
00237                 }
00238 
00239                 // Fall back to default.
00240                 if ( array_key_exists( 'default', $thisSetting ) ) {
00241                     if ( is_array( $retval ) && is_array( $thisSetting['default'] ) ) {
00242                         $retval = self::arrayMerge( $retval, $thisSetting['default'] );
00243                     } else {
00244                         $retval = $thisSetting['default'];
00245                     }
00246                     break;
00247                 }
00248             } while ( false );
00249         }
00250 
00251         if ( !is_null( $retval ) && count( $params['params'] ) ) {
00252             foreach ( $params['params'] as $key => $value ) {
00253                 $retval = $this->doReplace( '$' . $key, $value, $retval );
00254             }
00255         }
00256         return $retval;
00257     }
00258 
00268     function doReplace( $from, $to, $in ) {
00269         if ( is_string( $in ) ) {
00270             return str_replace( $from, $to, $in );
00271         } elseif ( is_array( $in ) ) {
00272             foreach ( $in as $key => $val ) {
00273                 $in[$key] = $this->doReplace( $from, $to, $val );
00274             }
00275             return $in;
00276         } else {
00277             return $in;
00278         }
00279     }
00280 
00289     public function getAll( $wiki, $suffix = null, $params = array(), $wikiTags = array() ) {
00290         $params = $this->mergeParams( $wiki, $suffix, $params, $wikiTags );
00291         $localSettings = array();
00292         foreach ( $this->settings as $varname => $stuff ) {
00293             $append = false;
00294             $var = $varname;
00295             if ( substr( $varname, 0, 1 ) == '+' ) {
00296                 $append = true;
00297                 $var = substr( $varname, 1 );
00298             }
00299 
00300             $value = $this->getSetting( $varname, $wiki, $params );
00301             if ( $append && is_array( $value ) && is_array( $GLOBALS[$var] ) ) {
00302                 $value = self::arrayMerge( $value, $GLOBALS[$var] );
00303             }
00304             if ( !is_null( $value ) ) {
00305                 $localSettings[$var] = $value;
00306             }
00307         }
00308         return $localSettings;
00309     }
00310 
00319     public function getBool( $setting, $wiki, $suffix = null, $wikiTags = array() ) {
00320         return (bool)$this->get( $setting, $wiki, $suffix, array(), $wikiTags );
00321     }
00322 
00328     function &getLocalDatabases() {
00329         return $this->wikis;
00330     }
00331 
00341     public function extractVar( $setting, $wiki, $suffix, &$var, $params = array(), $wikiTags = array() ) {
00342         $value = $this->get( $setting, $wiki, $suffix, $params, $wikiTags );
00343         if ( !is_null( $value ) ) {
00344             $var = $value;
00345         }
00346     }
00347 
00356     public function extractGlobal( $setting, $wiki, $suffix = null, $params = array(), $wikiTags = array() ) {
00357         $params = $this->mergeParams( $wiki, $suffix, $params, $wikiTags );
00358         $this->extractGlobalSetting( $setting, $wiki, $params );
00359     }
00360 
00366     public function extractGlobalSetting( $setting, $wiki, $params ) {
00367         $value = $this->getSetting( $setting, $wiki, $params );
00368         if ( !is_null( $value ) ) {
00369             if ( substr( $setting, 0, 1 ) == '+' && is_array( $value ) ) {
00370                 $setting = substr( $setting, 1 );
00371                 if ( is_array( $GLOBALS[$setting] ) ) {
00372                     $GLOBALS[$setting] = self::arrayMerge( $GLOBALS[$setting], $value );
00373                 } else {
00374                     $GLOBALS[$setting] = $value;
00375                 }
00376             } else {
00377                 $GLOBALS[$setting] = $value;
00378             }
00379         }
00380     }
00381 
00389     public function extractAllGlobals( $wiki, $suffix = null, $params = array(), $wikiTags = array() ) {
00390         $params = $this->mergeParams( $wiki, $suffix, $params, $wikiTags );
00391         foreach ( $this->settings as $varName => $setting ) {
00392             $this->extractGlobalSetting( $varName, $wiki, $params );
00393         }
00394     }
00395 
00404     protected function getWikiParams( $wiki ) {
00405         static $default = array(
00406             'suffix' => null,
00407             'lang' => null,
00408             'tags' => array(),
00409             'params' => array(),
00410         );
00411 
00412         if ( !is_callable( $this->siteParamsCallback ) ) {
00413             return $default;
00414         }
00415 
00416         $ret = call_user_func_array( $this->siteParamsCallback, array( $this, $wiki ) );
00417         # Validate the returned value
00418         if ( !is_array( $ret ) ) {
00419             return $default;
00420         }
00421 
00422         foreach ( $default as $name => $def ) {
00423             if ( !isset( $ret[$name] ) || ( is_array( $default[$name] ) && !is_array( $ret[$name] ) ) ) {
00424                 $ret[$name] = $default[$name];
00425             }
00426         }
00427 
00428         return $ret;
00429     }
00430 
00443     protected function mergeParams( $wiki, $suffix, /*array*/ $params, /*array*/ $wikiTags ) {
00444         $ret = $this->getWikiParams( $wiki );
00445 
00446         if ( is_null( $ret['suffix'] ) ) {
00447             $ret['suffix'] = $suffix;
00448         }
00449 
00450         $ret['tags'] = array_unique( array_merge( $ret['tags'], $wikiTags ) );
00451 
00452         $ret['params'] += $params;
00453 
00454         // Automatically fill that ones if needed
00455         if ( !isset( $ret['params']['lang'] ) && !is_null( $ret['lang'] ) ) {
00456             $ret['params']['lang'] = $ret['lang'];
00457         }
00458         if ( !isset( $ret['params']['site'] ) && !is_null( $ret['suffix'] ) ) {
00459             $ret['params']['site'] = $ret['suffix'];
00460         }
00461 
00462         return $ret;
00463     }
00464 
00471     public function siteFromDB( $db ) {
00472         // Allow override
00473         $def = $this->getWikiParams( $db );
00474         if ( !is_null( $def['suffix'] ) && !is_null( $def['lang'] ) ) {
00475             return array( $def['suffix'], $def['lang'] );
00476         }
00477 
00478         $site = null;
00479         $lang = null;
00480         foreach ( $this->suffixes as $altSite => $suffix ) {
00481             if ( $suffix === '' ) {
00482                 $site = '';
00483                 $lang = $db;
00484                 break;
00485             } elseif ( substr( $db, -strlen( $suffix ) ) == $suffix ) {
00486                 $site = is_numeric( $altSite ) ? $suffix : $altSite;
00487                 $lang = substr( $db, 0, strlen( $db ) - strlen( $suffix ) );
00488                 break;
00489             }
00490         }
00491         $lang = str_replace( '_', '-', $lang );
00492         return array( $site, $lang );
00493     }
00494 
00506     public function getConfig( $wiki, $settings ) {
00507         global $IP;
00508 
00509         $multi = is_array( $settings );
00510         $settings = (array)$settings;
00511         if ( $wiki === wfWikiID() ) { // $wiki is this wiki
00512             $res = array();
00513             foreach ( $settings as $name ) {
00514                 if ( !preg_match( '/^wg[A-Z]/', $name ) ) {
00515                     throw new MWException( "Variable '$name' does start with 'wg'." );
00516                 } elseif ( !isset( $GLOBALS[$name] ) ) {
00517                     throw new MWException( "Variable '$name' is not set." );
00518                 }
00519                 $res[$name] = $GLOBALS[$name];
00520             }
00521         } else { // $wiki is a foreign wiki
00522             if ( isset( $this->cfgCache[$wiki] ) ) {
00523                 $res = array_intersect_key( $this->cfgCache[$wiki], array_flip( $settings ) );
00524                 if ( count( $res ) == count( $settings ) ) {
00525                     return $res; // cache hit
00526                 }
00527             } elseif ( !in_array( $wiki, $this->wikis ) ) {
00528                 throw new MWException( "No such wiki '$wiki'." );
00529             } else {
00530                 $this->cfgCache[$wiki] = array();
00531             }
00532             $retVal = 1;
00533             $cmd = wfShellWikiCmd(
00534                 "$IP/maintenance/getConfiguration.php",
00535                 array(
00536                     '--wiki', $wiki,
00537                     '--settings', implode( ' ', $settings ),
00538                     '--format', 'PHP'
00539                 )
00540             );
00541             // ulimit5.sh breaks this call
00542             $data = trim( wfShellExec( $cmd, $retVal, array(), array( 'memory' => 0 ) ) );
00543             if ( $retVal != 0 || !strlen( $data ) ) {
00544                 throw new MWException( "Failed to run getConfiguration.php." );
00545             }
00546             $res = unserialize( $data );
00547             if ( !is_array( $res ) ) {
00548                 throw new MWException( "Failed to unserialize configuration array." );
00549             }
00550             $this->cfgCache[$wiki] = $this->cfgCache[$wiki] + $res;
00551         }
00552 
00553         return $multi ? $res : current( $res );
00554     }
00555 
00561     public function isLocalVHost( $vhost ) {
00562         return in_array( $vhost, $this->localVHosts );
00563     }
00564 
00575     static function arrayMerge( $array1/* ... */ ) {
00576         $out = $array1;
00577         for ( $i = 1; $i < func_num_args(); $i++ ) {
00578             foreach ( func_get_arg( $i ) as $key => $value ) {
00579                 if ( isset( $out[$key] ) && is_array( $out[$key] ) && is_array( $value ) ) {
00580                     $out[$key] = self::arrayMerge( $out[$key], $value );
00581                 } elseif ( !isset( $out[$key] ) || !$out[$key] && !is_numeric( $key ) ) {
00582                     // Values that evaluate to true given precedence, for the primary purpose of merging permissions arrays.
00583                     $out[$key] = $value;
00584                 } elseif ( is_numeric( $key ) ) {
00585                     $out[] = $value;
00586                 }
00587             }
00588         }
00589 
00590         return $out;
00591     }
00592 
00593     public function loadFullData() {
00594         if ( $this->fullLoadCallback && !$this->fullLoadDone ) {
00595             call_user_func( $this->fullLoadCallback, $this );
00596             $this->fullLoadDone = true;
00597         }
00598     }
00599 }