* removed DEFAULT '' NOT NULL constraints as '' is internaly converted to NULL in...
[lhc/web/wiklou.git] / includes / installer / DatabaseUpdater.php
index 6ba2df3..c519087 100644 (file)
@@ -30,12 +30,6 @@ abstract class DatabaseUpdater {
         */
        protected $extensionUpdates = array();
 
-       /**
-        * Used to hold schema files during installation process
-        * @var array
-        */
-       protected $newExtensions = array();
-
        /**
         * Handle to the database subclass
         *
@@ -65,7 +59,9 @@ abstract class DatabaseUpdater {
                } else {
                        $this->maintenance = new FakeMaintenance;
                }
+               $this->maintenance->setDB( $db );
                $this->initOldGlobals();
+               $this->loadExtensions();
                wfRunHooks( 'LoadExtensionSchemaUpdates', array( $this ) );
        }
 
@@ -88,7 +84,25 @@ abstract class DatabaseUpdater {
        }
 
        /**
-        * @static
+        * Loads LocalSettings.php, if needed, and initialises everything needed for LoadExtensionSchemaUpdates hook
+        */
+       private function loadExtensions() {
+               if ( !defined( 'MEDIAWIKI_INSTALL' ) ) {
+                       return; // already loaded
+               }
+               $vars = Installer::getExistingLocalSettings();
+               if ( !$vars ) {
+                       return; // no LocalSettings found
+               }
+               if ( !isset( $vars['wgHooks'] ) || !isset( $vars['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
+                       return;
+               }
+               global $wgHooks, $wgAutoloadClasses;
+               $wgHooks['LoadExtensionSchemaUpdates'] = $vars['wgHooks']['LoadExtensionSchemaUpdates'];
+               $wgAutoloadClasses = $wgAutoloadClasses + $vars['wgAutoloadClasses'];
+       }
+
+       /**
         * @throws MWException
         * @param DatabaseBase $db
         * @param bool $shared
@@ -156,23 +170,6 @@ abstract class DatabaseUpdater {
                $this->extensionUpdates[] = array( 'addTable', $tableName, $sqlPath, true );
        }
 
-       /**
-        * Add a brand new extension to MediaWiki. Used during the initial install
-        * @param $ext String Name of extension
-        * @param $sqlPath String Full path to the schema file
-        */
-       public function addNewExtension( $ext, $sqlPath ) {
-               $this->newExtensions[ strtolower( $ext ) ] = $sqlPath;
-       }
-
-       /**
-        * Get the list of extensions that registered a schema with our DB type
-        * @return array
-        */
-       public function getNewExtensions() {
-               return $this->newExtensions;
-       }
-
        /**
         * Get the list of extension-defined updates
         *
@@ -189,21 +186,28 @@ abstract class DatabaseUpdater {
        /**
         * Do all the updates
         *
-        * @param $purge Boolean: whether to clear the objectcache table after updates
+        * @param $what Array: what updates to perform
         */
-       public function doUpdates( $purge = true ) {
+       public function doUpdates( $what = array( 'core', 'extensions', 'purge' ) ) {
                global $wgVersion;
 
-               $this->runUpdates( $this->getCoreUpdateList(), false );
-               $this->runUpdates( $this->getOldGlobalUpdates(), false );
-               $this->runUpdates( $this->getExtensionUpdates(), true );
+               $what = array_flip( $what );
+               if ( isset( $what['core'] ) ) {
+                       $this->runUpdates( $this->getCoreUpdateList(), false );
+               }
+               if ( isset( $what['extensions'] ) ) {
+                       $this->runUpdates( $this->getOldGlobalUpdates(), false );
+                       $this->runUpdates( $this->getExtensionUpdates(), true );
+               }
 
                $this->setAppliedUpdates( $wgVersion, $this->updates );
 
-               if( $purge ) {
+               if( isset( $what['purge'] ) ) {
                        $this->purgeCache();
                }
-               $this->checkStats();
+               if ( isset( $what['core'] ) ) {
+                       $this->checkStats();
+               }
        }
 
        /**
@@ -228,6 +232,7 @@ abstract class DatabaseUpdater {
        }
 
        protected function setAppliedUpdates( $version, $updates = array() ) {
+               $this->db->clearFlag( DBO_DDLMODE );
                if( !$this->canUseNewUpdatelog() ) {
                        return;
                }
@@ -235,12 +240,14 @@ abstract class DatabaseUpdater {
                $this->db->insert( 'updatelog',
                        array( 'ul_key' => $key, 'ul_value' => serialize( $updates ) ),
                         __METHOD__ );
+               $this->db->setFlag( DBO_DDLMODE );
        }
 
        /**
         * Helper function: check if the given key is present in the updatelog table.
         * Obviously, only use this for updates that occur after the updatelog table was
         * created!
+        * @param $key String Name of the key to check for
         */
        public function updateRowExists( $key ) {
                $row = $this->db->selectRow(
@@ -252,6 +259,23 @@ abstract class DatabaseUpdater {
                return (bool)$row;
        }
 
+       /**
+        * Helper function: Add a key to the updatelog table
+        * Obviously, only use this for updates that occur after the updatelog table was
+        * created!
+        * @param $key String Name of key to insert
+        * @param $val String [optional] value to insert along with the key
+        */
+       public function insertUpdateRow( $key, $val = null ) {
+               $this->db->clearFlag( DBO_DDLMODE );
+               $values = array( 'ul_key' => $key );
+               if( $val && $this->canUseNewUpdatelog() ) {
+                       $values['ul_value'] = $val;
+               }
+               $this->db->insert( 'updatelog', $values, __METHOD__, 'IGNORE' );
+               $this->db->setFlag( DBO_DDLMODE );
+       }
+
        /**
         * Updatelog was changed in 1.17 to have a ul_value column so we can record
         * more information about what kind of updates we've done (that's what this
@@ -433,13 +457,17 @@ abstract class DatabaseUpdater {
         * @param $fullpath Boolean: whether to treat $patch path as a relative or not
         */
        public function modifyField( $table, $field, $patch, $fullpath = false ) {
+               $updateKey = "$table-$field-$patch";
                if ( !$this->db->tableExists( $table ) ) {
                        $this->output( "...$table table does not exist, skipping modify field patch\n" );
                } elseif ( !$this->db->fieldExists( $table, $field ) ) {
                        $this->output( "...$field field does not exist in $table table, skipping modify field patch\n" );
+               } elseif( $this->updateRowExists( $updateKey ) ) {
+                       $this->output( "...$field in table $table already modified by patch $patch\n" );
                } else {
                        $this->output( "Modifying $field field of table $table..." );
                        $this->applyPatch( $patch, $fullpath );
+                       $this->insertUpdateRow( $updateKey );
                        $this->output( "ok\n" );
                }
        }
@@ -489,6 +517,21 @@ abstract class DatabaseUpdater {
                $this->output( "...ss_active_users user count set...\n" );
        }
 
+       protected function doLogUsertextPopulation() {
+               if ( $this->updateRowExists( 'populate log_usertext' ) ) {
+                       $this->output( "...log_user_text field already populated.\n" );
+                       return;
+               }
+
+               $this->output(
+                       "Populating log_user_text field, printing progress markers. For large\n" .
+                       "databases, you may want to hit Ctrl-C and do this manually with\n" .
+                       "maintenance/populateLogUsertext.php.\n" );
+               $task = $this->maintenance->runChild( 'PopulateLogUsertext' );
+               $task->execute();
+               $this->output( "Done populating log_user_text field.\n" );
+       }
+
        protected function doLogSearchPopulation() {
                if ( $this->updateRowExists( 'populate log_search' ) ) {
                        $this->output( "...log_search table already populated.\n" );
@@ -499,7 +542,7 @@ abstract class DatabaseUpdater {
                        "Populating log_search table, printing progress markers. For large\n" .
                        "databases, you may want to hit Ctrl-C and do this manually with\n" .
                        "maintenance/populateLogSearch.php.\n" );
-               $task = new PopulateLogSearch();
+               $task = $this->maintenance->runChild( 'PopulateLogSearch' );
                $task->execute();
                $this->output( "Done populating log_search table.\n" );
        }
@@ -527,7 +570,7 @@ abstract class DatabaseUpdater {
                        return;
                }
 
-               $task = new UpdateCollation();
+               $task = $this->maintenance->runChild( 'UpdateCollation' );
                $task->execute();
        }
 }