*/
class ExtensionRegistry {
+ /**
+ * "requires" key that applies to MediaWiki core/$wgVersion
+ */
+ const MEDIAWIKI_CORE = 'MediaWiki';
+
/**
* Version of the highest supported manifest version
*/
/**
* Bump whenever the registration cache needs resetting
*/
- const CACHE_VERSION = 1;
+ const CACHE_VERSION = 3;
/**
* Special key that defines the merge strategy
*
* @var array
*/
- private $loaded = array();
+ private $loaded = [];
/**
* List of paths that should be loaded
*
* @var array
*/
- protected $queued = array();
+ protected $queued = [];
/**
* Items in the JSON file that aren't being
*
* @var array
*/
- protected $attributes = array();
+ protected $attributes = [];
/**
* @var ExtensionRegistry
// we don't want to fail here if $wgObjectCaches is not configured
// properly for APC setup
try {
- $this->cache = ObjectCache::newAccelerator();
+ $this->cache = ObjectCache::getLocalServerInstance();
} catch ( MWException $e ) {
$this->cache = new EmptyBagOStuff();
}
}
public function loadFromQueue() {
+ global $wgVersion;
if ( !$this->queued ) {
return;
}
+ // A few more things to vary the cache on
+ $versions = [
+ 'registration' => self::CACHE_VERSION,
+ 'mediawiki' => $wgVersion
+ ];
+
// See if this queue is in APC
- $key = wfMemcKey( 'registration', md5( json_encode( $this->queued ) ), self::CACHE_VERSION );
+ $key = wfMemcKey(
+ 'registration',
+ md5( json_encode( $this->queued + $versions ) )
+ );
$data = $this->cache->get( $key );
if ( $data ) {
$this->exportExtractedData( $data );
unset( $data['autoload'] );
$this->cache->set( $key, $data, 60 * 60 * 24 );
}
- $this->queued = array();
+ $this->queued = [];
}
/**
* outside of the installer.
*/
public function clearQueue() {
- $this->queued = array();
+ $this->queued = [];
}
/**
* @throws Exception
*/
public function readFromQueue( array $queue ) {
- $autoloadClasses = array();
+ global $wgVersion;
+ $autoloadClasses = [];
+ $autoloaderPaths = [];
$processor = new ExtensionProcessor();
+ $incompatible = [];
+ $coreVersionParser = new CoreVersionChecker( $wgVersion );
foreach ( $queue as $path => $mtime ) {
$json = file_get_contents( $path );
if ( $json === false ) {
// Set up the autoloader now so custom processors will work
$GLOBALS['wgAutoloadClasses'] += $autoload;
$autoloadClasses += $autoload;
+ // Check any constraints against MediaWiki core
+ $requires = $processor->getRequirements( $info );
+ if ( isset( $requires[self::MEDIAWIKI_CORE] )
+ && !$coreVersionParser->check( $requires[self::MEDIAWIKI_CORE] )
+ ) {
+ // Doesn't match, mark it as incompatible.
+ $incompatible[] = "{$info['name']} is not compatible with the current "
+ . "MediaWiki core (version {$wgVersion}), it requires: " . $requires[self::MEDIAWIKI_CORE]
+ . '.';
+ continue;
+ }
+ // Get extra paths for later inclusion
+ $autoloaderPaths = array_merge( $autoloaderPaths,
+ $processor->getExtraAutoloaderPaths( dirname( $path ), $info ) );
+ // Compatible, read and extract info
$processor->extractInfo( $path, $info, $version );
}
+ if ( $incompatible ) {
+ if ( count( $incompatible ) === 1 ) {
+ throw new Exception( $incompatible[0] );
+ } else {
+ throw new Exception( implode( "\n", $incompatible ) );
+ }
+ }
$data = $processor->getExtractedInfo();
// Need to set this so we can += to it later
- $data['globals']['wgAutoloadClasses'] = array();
- foreach ( $data['credits'] as $credit ) {
- $data['globals']['wgExtensionCredits'][$credit['type']][] = $credit;
- }
- $data['globals']['wgExtensionCredits'][self::MERGE_STRATEGY] = 'array_merge_recursive';
+ $data['globals']['wgAutoloadClasses'] = [];
$data['autoload'] = $autoloadClasses;
+ $data['autoloaderPaths'] = $autoloaderPaths;
return $data;
}
foreach ( $info['globals'] as $key => $val ) {
// If a merge strategy is set, read it and remove it from the value
// so it doesn't accidentally end up getting set.
- // Need to check $val is an array for PHP 5.3 which will return
- // true on isset( 'string'['foo'] ).
- if ( isset( $val[self::MERGE_STRATEGY] ) && is_array( $val ) ) {
+ if ( is_array( $val ) && isset( $val[self::MERGE_STRATEGY] ) ) {
$mergeStrategy = $val[self::MERGE_STRATEGY];
unset( $val[self::MERGE_STRATEGY] );
} else {
$GLOBALS[$key] = wfArrayPlus2d( $GLOBALS[$key], $val );
break;
case 'array_plus':
- $GLOBALS[$key] = $val + $GLOBALS[$key];
+ $GLOBALS[$key] += $val;
break;
case 'array_merge':
$GLOBALS[$key] = array_merge( $val, $GLOBALS[$key] );
foreach ( $info['defines'] as $name => $val ) {
define( $name, $val );
}
+ foreach ( $info['autoloaderPaths'] as $path ) {
+ require_once $path;
+ }
foreach ( $info['callbacks'] as $cb ) {
call_user_func( $cb );
}
$this->loaded += $info['credits'];
-
if ( $info['attributes'] ) {
if ( !$this->attributes ) {
$this->attributes = $info['attributes'];
if ( isset( $this->attributes[$name] ) ) {
return $this->attributes[$name];
} else {
- return array();
+ return [];
}
}
return "$dir/$file";
}, $info['AutoloadClasses'] );
} else {
- return array();
+ return [];
}
}
}