maintenance: Allow having a nicer error message if an extension isn't enabled
authorKunal Mehta <legoktm@member.fsf.org>
Thu, 28 Jul 2016 21:44:06 +0000 (14:44 -0700)
committerReedy <reedy@wikimedia.org>
Sat, 30 Jul 2016 10:38:51 +0000 (10:38 +0000)
Maintenance scripts can be invoked regardless of whether an extension is
enabled on a wiki or not. On wiki farms where some wikis may have an
extension or not, this can potentially be rather confusing. Especially
when the script bails out with a fatal class missing error or a database
table missing.

This allows maintenance scripts to specify that they require an
extension by calling:
 $this->requireExtension( 'ExtensionName' );
in the script's constructor.

Bug: T141531
Change-Id: Icfbf063bb9c9ac9e55c3a5a8ed815528a2c1ce1e

RELEASE-NOTES-1.28
maintenance/Maintenance.php
maintenance/doMaintenance.php

index cff734b..41e94be 100644 (file)
@@ -36,6 +36,8 @@ production.
 * Added a new hook, 'UploadVerifyUpload', which can be used to reject a file
   upload. Unlike 'UploadVerifyFile' it provides information about upload comment
   and the file description page, but does not run for uploads to stash.
+* (T141604) Extensions can now provide a better error message when their
+  maintenance scripts are run without the extension being installed.
 
 === External library changes in 1.28 ===
 
index 27d8161..8368aab 100644 (file)
@@ -123,6 +123,12 @@ abstract class Maintenance {
         */
        private $config;
 
+       /**
+        * @see Maintenance::requireExtension
+        * @var array
+        */
+       private $requiredExtensions = [];
+
        /**
         * Used to read the options in the order they were passed.
         * Useful for option chaining (Ex. dumpBackup.php). It will
@@ -506,6 +512,42 @@ abstract class Maintenance {
                $this->config = $config;
        }
 
+       /**
+        * Indicate that the specified extension must be
+        * loaded before the script can run.
+        *
+        * This *must* be called in the constructor.
+        *
+        * @since 1.28
+        * @param string $name
+        */
+       protected function requireExtension( $name ) {
+               $this->requiredExtensions[] = $name;
+       }
+
+       /**
+        * Verify that the required extensions are installed
+        *
+        * @since 1.28
+        */
+       public function checkRequiredExtensions() {
+               $registry = ExtensionRegistry::getInstance();
+               $missing = [];
+               foreach ( $this->requiredExtensions as $name ) {
+                       if ( !$registry->isLoaded( $name ) ) {
+                               $missing[] = $name;
+                       }
+               }
+
+               if ( $missing ) {
+                       $joined = implode( ', ', $missing );
+                       $msg = "The following extensions are required to be installed "
+                               . "for this script to run: $joined. Please enable them and then try again.";
+                       $this->error( $msg, 1 );
+               }
+
+       }
+
        /**
         * Run a child maintenance script. Pass all of the current arguments
         * to it.
index 000e5f9..1272ca2 100644 (file)
@@ -99,6 +99,9 @@ require_once "$IP/includes/Setup.php";
 // Initialize main config instance
 $maintenance->setConfig( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
 
+// Sanity-check required extensions are installed
+$maintenance->checkRequiredExtensions();
+
 // Do the work
 $maintenance->execute();