Florianschmidtwelzow has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/358177 )
Change subject: Try to autoload required, but not installed extensions ...................................................................... Try to autoload required, but not installed extensions If an extension is present in the extension directory, required by another, already installed extension, but not being installed explicitly, MediaWiki would throw an exception until now. This change adds an autoloader mechanism for extensions, which are required by other extensions and present in the extension directory (installed using Extension registration). Bug: T152263 Change-Id: I2a4c9b63328ad146060b3def7a699e1c6229bd2c --- M includes/registration/ExtensionRegistry.php M includes/registration/VersionChecker.php 2 files changed, 68 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/77/358177/1 diff --git a/includes/registration/ExtensionRegistry.php b/includes/registration/ExtensionRegistry.php index 0c5a67e..8166e67 100644 --- a/includes/registration/ExtensionRegistry.php +++ b/includes/registration/ExtensionRegistry.php @@ -253,6 +253,7 @@ $incompatible, $versionChecker ->setLoadedExtensionsAndSkins( $data['credits'] ) + ->setExtensionNotLoadedCallback( [ $this, 'attemptLoadRequiredExtension' ] ) ->checkArray( $extDependencies ) ); @@ -271,6 +272,36 @@ return $data; } + /** + * Callback function for VersionChecker, which is called, when an extension is not loaded. + * Tries to load this extension on the fly using extension registration and will return the + * extension credits, if loading it succeeds, false otherwise. + * + * @param $extensionName + * @return bool|array + */ + public function attemptLoadRequiredExtension( $extensionName ) { + global $wgExtensionDirectory; + $path = "$wgExtensionDirectory/$extensionName/extension.json"; + + // save the currently queued extensions to later re-apply them + $originalQueue = $this->queued; + $this->queued = []; + try { + $this->queue( $path ); + } catch ( Exception $e ) { + $this->queued = $originalQueue; + // something went wrong, let's assume that the extension could not be loaded + return false; + } + $this->loadFromQueue(); + $this->queued = $originalQueue; + if ( $this->isLoaded( $extensionName ) ) { + return $this->getAllThings()[$extensionName]; + } + return false; + } + 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 diff --git a/includes/registration/VersionChecker.php b/includes/registration/VersionChecker.php index a31551c..e26274a 100644 --- a/includes/registration/VersionChecker.php +++ b/includes/registration/VersionChecker.php @@ -46,6 +46,11 @@ private $versionParser; /** + * @var callable A callable, which is called whenever an extension is not loaded. + */ + private $extensionNotLoadedCallback; + + /** * @param string $coreVersion Current version of core */ public function __construct( $coreVersion ) { @@ -169,7 +174,18 @@ private function handleExtensionDependency( $dependencyName, $constraint, $checkedExt ) { // Check if the dependency is even installed if ( !isset( $this->loaded[$dependencyName] ) ) { - return "{$checkedExt} requires {$dependencyName} to be installed."; + // if the extension isn't installed, execute the callback, which could load the + // extension on the fly and return the required information + $extensionData = null; + if ( is_callable( $this->extensionNotLoadedCallback ) ) { + $extensionData = call_user_func_array( + $this->extensionNotLoadedCallback, [ $dependencyName ] ); + } + if ( is_array( $extensionData ) ) { + $this->loaded[$dependencyName] = $extensionData; + } else { + return "{$checkedExt} requires {$dependencyName} to be installed."; + } } // Check if the dependency has specified a version if ( !isset( $this->loaded[$dependencyName]['version'] ) ) { @@ -208,4 +224,24 @@ return false; } + + /** + * Sets the notLoadedCallback, which is called whenever a required extension is not loaded. + * The callback can return an array of information about that extension, which will then be + * merged into the already passed in array of loaded extensions. If this is the case, the + * requirement is further handled as it would be loaded in the first place. + * + * If nothing or false is returned, the extension will be handled as if it would not be loaded. + * + * When the callback is called, it will have the name of the required extension as the first + * parameter. + * + * @param callable $cb + * @return VersionChecker + */ + public function setExtensionNotLoadedCallback( callable $cb ) { + $this->extensionNotLoadedCallback = $cb; + + return $this; + } } -- To view, visit https://gerrit.wikimedia.org/r/358177 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2a4c9b63328ad146060b3def7a699e1c6229bd2c Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits