summaryrefslogtreecommitdiff
path: root/includes/registration
diff options
context:
space:
mode:
Diffstat (limited to 'includes/registration')
-rw-r--r--includes/registration/ExtensionProcessor.php41
-rw-r--r--includes/registration/ExtensionRegistry.php84
2 files changed, 105 insertions, 20 deletions
diff --git a/includes/registration/ExtensionProcessor.php b/includes/registration/ExtensionProcessor.php
index bb8fb329..0b594b42 100644
--- a/includes/registration/ExtensionProcessor.php
+++ b/includes/registration/ExtensionProcessor.php
@@ -47,6 +47,24 @@ class ExtensionProcessor implements Processor {
);
/**
+ * Mapping of global settings to their specific merge strategies.
+ *
+ * @see ExtensionRegistry::exportExtractedData
+ * @see getExtractedInfo
+ * @var array
+ */
+ protected static $mergeStrategies = array(
+ 'wgGroupPermissions' => 'array_plus_2d',
+ 'wgRevokePermissions' => 'array_plus_2d',
+ 'wgHooks' => 'array_merge_recursive',
+ // credits are handled in the ExtensionRegistry
+ //'wgExtensionCredits' => 'array_merge_recursive',
+ 'wgExtraGenderNamespaces' => 'array_plus',
+ 'wgNamespacesWithSubpages' => 'array_plus',
+ 'wgNamespaceContentModels' => 'array_plus',
+ );
+
+ /**
* Keys that are part of the extension credits
*
* @var array
@@ -155,6 +173,13 @@ class ExtensionProcessor implements Processor {
}
public function getExtractedInfo() {
+ // Make sure the merge strategies are set
+ foreach ( $this->globals as $key => $val ) {
+ if ( isset( self::$mergeStrategies[$key] ) ) {
+ $this->globals[$key][ExtensionRegistry::MERGE_STRATEGY] = self::$mergeStrategies[$key];
+ }
+ }
+
return array(
'globals' => $this->globals,
'defines' => $this->defines,
@@ -166,8 +191,10 @@ class ExtensionProcessor implements Processor {
protected function extractHooks( array $info ) {
if ( isset( $info['Hooks'] ) ) {
- foreach ( $info['Hooks'] as $name => $callable ) {
- $this->globals['wgHooks'][$name][] = $callable;
+ foreach ( $info['Hooks'] as $name => $value ) {
+ foreach ( (array)$value as $callback ) {
+ $this->globals['wgHooks'][$name][] = $callback;
+ }
}
}
}
@@ -182,7 +209,7 @@ class ExtensionProcessor implements Processor {
foreach ( $info['namespaces'] as $ns ) {
$id = $ns['id'];
$this->defines[$ns['constant']] = $id;
- $this->globals['wgExtraNamespaces'][$id] = $ns['name'];
+ $this->attributes['ExtensionNamespaces'][$id] = $ns['name'];
if ( isset( $ns['gender'] ) ) {
$this->globals['wgExtraGenderNamespaces'][$id] = $ns['gender'];
}
@@ -269,9 +296,15 @@ class ExtensionProcessor implements Processor {
*/
protected function extractConfig( array $info ) {
if ( isset( $info['config'] ) ) {
+ if ( isset( $info['config']['_prefix'] ) ) {
+ $prefix = $info['config']['_prefix'];
+ unset( $info['config']['_prefix'] );
+ } else {
+ $prefix = 'wg';
+ }
foreach ( $info['config'] as $key => $val ) {
if ( $key[0] !== '@' ) {
- $this->globals["wg$key"] = $val;
+ $this->globals["$prefix$key"] = $val;
}
}
}
diff --git a/includes/registration/ExtensionRegistry.php b/includes/registration/ExtensionRegistry.php
index 4e690aa8..16d83356 100644
--- a/includes/registration/ExtensionRegistry.php
+++ b/includes/registration/ExtensionRegistry.php
@@ -12,6 +12,28 @@
class ExtensionRegistry {
/**
+ * Version of the highest supported manifest version
+ */
+ const MANIFEST_VERSION = 1;
+
+ /**
+ * Version of the oldest supported manifest version
+ */
+ const OLDEST_MANIFEST_VERSION = 1;
+
+ /**
+ * Bump whenever the registration cache needs resetting
+ */
+ const CACHE_VERSION = 1;
+
+ /**
+ * Special key that defines the merge strategy
+ *
+ * @since 1.26
+ */
+ const MERGE_STRATEGY = '_merge_strategy';
+
+ /**
* @var BagOStuff
*/
protected $cache;
@@ -92,7 +114,7 @@ class ExtensionRegistry {
}
// See if this queue is in APC
- $key = wfMemcKey( 'registration', md5( json_encode( $this->queued ) ) );
+ $key = wfMemcKey( 'registration', md5( json_encode( $this->queued ) ), self::CACHE_VERSION );
$data = $this->cache->get( $key );
if ( $data ) {
$this->exportExtractedData( $data );
@@ -155,31 +177,61 @@ class ExtensionRegistry {
foreach ( $data['credits'] as $credit ) {
$data['globals']['wgExtensionCredits'][$credit['type']][] = $credit;
}
+ $data['globals']['wgExtensionCredits'][self::MERGE_STRATEGY] = 'array_merge_recursive';
$data['autoload'] = $autoloadClasses;
return $data;
}
protected function exportExtractedData( array $info ) {
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 ) ) {
+ $mergeStrategy = $val[self::MERGE_STRATEGY];
+ unset( $val[self::MERGE_STRATEGY] );
+ } else {
+ $mergeStrategy = 'array_merge';
+ }
+
+ // Optimistic: If the global is not set, or is an empty array, replace it entirely.
+ // Will be O(1) performance.
if ( !isset( $GLOBALS[$key] ) || ( is_array( $GLOBALS[$key] ) && !$GLOBALS[$key] ) ) {
$GLOBALS[$key] = $val;
- } elseif ( $key === 'wgHooks' || $key === 'wgExtensionCredits' ) {
- // Special case $wgHooks and $wgExtensionCredits, which require a recursive merge.
- // Ideally it would have been taken care of in the first if block though.
- $GLOBALS[$key] = array_merge_recursive( $GLOBALS[$key], $val );
- } elseif ( $key === 'wgGroupPermissions' ) {
- // First merge individual groups
- foreach ( $GLOBALS[$key] as $name => &$groupVal ) {
- if ( isset( $val[$name] ) ) {
- $groupVal += $val[$name];
+ continue;
+ }
+
+ if ( !is_array( $GLOBALS[$key] ) || !is_array( $val ) ) {
+ // config setting that has already been overridden, don't set it
+ continue;
+ }
+
+ switch ( $mergeStrategy ) {
+ case 'array_merge_recursive':
+ $GLOBALS[$key] = array_merge_recursive( $GLOBALS[$key], $val );
+ break;
+ case 'array_plus_2d':
+ // First merge items that are in both arrays
+ foreach ( $GLOBALS[$key] as $name => &$groupVal ) {
+ if ( isset( $val[$name] ) ) {
+ $groupVal += $val[$name];
+ }
}
- }
- // Now merge groups that didn't exist yet
- $GLOBALS[$key] += $val;
- } elseif ( is_array( $GLOBALS[$key] ) && is_array( $val ) ) {
- $GLOBALS[$key] = array_merge( $val, $GLOBALS[$key] );
- } // else case is a config setting where it has already been overriden, so don't set it
+ // Now add items that didn't exist yet
+ $GLOBALS[$key] += $val;
+ break;
+ case 'array_plus':
+ $GLOBALS[$key] += $val;
+ break;
+ case 'array_merge':
+ $GLOBALS[$key] = array_merge( $val, $GLOBALS[$key] );
+ break;
+ default:
+ throw new UnexpectedValueException( "Unknown merge strategy '$mergeStrategy'" );
+ }
}
+
foreach ( $info['defines'] as $name => $val ) {
define( $name, $val );
}