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

Reply via email to