[schema change] Use new log_search table to replace ugly code from r48839. Maintenanc...
authorAaron Schulz <aaron@users.mediawiki.org>
Wed, 13 May 2009 22:03:32 +0000 (22:03 +0000)
committerAaron Schulz <aaron@users.mediawiki.org>
Wed, 13 May 2009 22:03:32 +0000 (22:03 +0000)
includes/LogEventsList.php
includes/LogPage.php
includes/specials/SpecialRevisiondelete.php
maintenance/populateLogSearch.php [new file with mode: 0644]
maintenance/tables.sql
maintenance/updaters.inc

index 7a6f3f8..1617fa4 100644 (file)
@@ -651,22 +651,29 @@ class LogPager extends ReverseChronologicalPager {
        }
 
        public function getQueryInfo() {
+               $tables = array( 'logging', 'user' );
                $this->mConds[] = 'user_id = log_user';
+               $index = array();
+               # Add log_search table if there are conditions on it
+               if( array_key_exists('ls_field',$this->mConds) ) {
+                       $tables[] = 'log_search';
+                       $index = array( 'log_search' => 'PRIMARY', 'logging' => 'PRIMARY' );
                # Don't use the wrong logging index
-               if( $this->title || $this->pattern || $this->user ) {
-                       $index = array( 'USE INDEX' => array( 'logging' => array('page_time','user_time') ) );
+               } else if( $this->title || $this->pattern || $this->user ) {
+                       $index = array( 'logging' => array('page_time','user_time') );
                } else if( $this->types ) {
-                       $index = array( 'USE INDEX' => array( 'logging' => 'type_time' ) );
+                       $index = array( 'logging' => 'type_time' );
                } else {
-                       $index = array( 'USE INDEX' => array( 'logging' => 'times' ) );
+                       $index = array( 'logging' => 'times' );
                }
                $info = array(
-                       'tables' => array( 'logging', 'user' ),
+                       'tables' => $tables,
                        'fields' => array( 'log_type', 'log_action', 'log_user', 'log_namespace', 'log_title', 'log_params',
                                'log_comment', 'log_id', 'log_deleted', 'log_timestamp', 'user_name', 'user_editcount' ),
                        'conds' => $this->mConds,
-                       'options' => $index,
-                       'join_conds' => array( 'user' => array( 'INNER JOIN', 'user_id=log_user' ) ),
+                       'options' => array( 'USE INDEX' => $index ),
+                       'join_conds' => array( 'user' => array( 'INNER JOIN', 'user_id=log_user' ),
+                               'log_search' => array( 'INNER JOIN', 'ls_log_id=log_id' ) ),
                );
 
                ChangeTags::modifyDisplayQuery( $info['tables'], $info['fields'], $info['conds'],
index 39869cb..bb4cecb 100644 (file)
@@ -91,7 +91,7 @@ class LogPage {
                                $this->type, $this->action, $this->target, $this->comment, $this->params, $newId );
                        $rc->notifyRC2UDP();
                }
-               return true;
+               return $newId;
        }
 
        /**
@@ -373,6 +373,22 @@ class LogPage {
 
                return $this->saveContent();
        }
+       
+       /**
+        * Add relations to log_search table
+        * @static
+        */
+       public function addRelations( $field, $values, $logid ) {
+               if( empty($values) )
+                       return false; // nothing
+               $data = array();
+               foreach( $values as $value ) {
+                       $data[] = array('ls_field' => $field,'ls_value' => $value,'ls_log_id' => $logid);
+               }
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->insert( 'log_search', $data, __METHOD__, 'IGNORE' );
+               return true;
+       }
 
        /**
         * Create a blob from a parameter array
index 5e27675..6bd0b1d 100644 (file)
@@ -85,16 +85,15 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        $this->showImages();
                } else if( $this->deleteKey == 'logid' ) {
                        $this->showLogItems();
-                       return; // no logs for now
                }
-               list($qc,$lim) = $this->getLogQueryCond();
+               $qc = $this->getLogQueryCond();
                # Show relevant lines from the deletion log
                $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'delete' ) ) . "</h2>\n" );
-               LogEventsList::showLogExtract( $wgOut, 'delete', $this->page->getPrefixedText(), '', $lim, $qc );
+               LogEventsList::showLogExtract( $wgOut, 'delete', $this->page->getPrefixedText(), '', 25, $qc );
                # Show relevant lines from the suppression log
                if( $wgUser->isAllowed( 'suppressionlog' ) ) {
                        $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'suppress' ) ) . "</h2>\n" );
-                       LogEventsList::showLogExtract( $wgOut, 'suppress', $this->page->getPrefixedText(), '', $lim, $qc );
+                       LogEventsList::showLogExtract( $wgOut, 'suppress', $this->page->getPrefixedText(), '', 25, $qc );
                }
        }
        
@@ -121,9 +120,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
        }
        
        private function getLogQueryCond() {
-               $ids = $safeIds = array();
-               $limit = 25; // default
-               $conds = array( 'log_action' => 'revision' ); // revision delete logs
+               $logAction = 'revision';
                switch( $this->deleteKey ) {
                        case 'oldid':
                                $ids = $this->oldids;
@@ -137,25 +134,19 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        case 'fileid':
                                $ids = $this->fileids;
                                break;
+                       case 'logid':
+                               $ids = $this->logids;
+                               $logAction = 'event';
+                               break;
                        default: // bad type?
-                               return array($conds,$limit);
-               }
-               // Just get the whole log if there are a lot if items
-               if( count($ids) > $limit )
-                       return array($conds,$limit);
-               // Digit chars only
-               foreach( $ids as $id ) {
-                       if( preg_match( '/^\d+$/', $id, $m ) ) {
-                               $safeIds[] = $m[0];
-                       }
-               }
-               // Format is <id1,id2,i3...>
-               if( count($safeIds) ) {
-                       $conds[] = "log_params RLIKE '^{$this->deleteKey}.*(^|\n|,)(".implode('|',$safeIds).")(,|\n|$)'";
-               } else {
-                       $conds = array('1=0');
-               }
-               return array($conds,$limit);
+                               return array();
+               }
+               // Revision delete logs for these item
+               $conds = array( 'log_action' => $logAction );
+               $conds['ls_field'] = RevisionDeleter::getRelationType( $this->deleteKey );
+               $conds['ls_value'] = $ids;
+               $conds[] = 'log_id = ls_log_id';
+               return $conds;
        }
 
        private function secureOperation() {
@@ -824,7 +815,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
        
        private function failure() {
                global $wgOut;
-               $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+               $wgOut->setPagetitle( wfMsg( 'actionfailed' ) );
                $wrap = '<span class="error">$1</span>';
                if( $this->deleteKey == 'logid' ) {
                        $this->showLogItems();
@@ -1540,18 +1531,41 @@ class RevisionDeleter {
                $param, $items = array() )
        {
                // Put things hidden from sysops in the oversight log
-               $logtype = ( ($nbitfield | $obitfield) & Revision::DELETED_RESTRICTED ) ?
+               $logType = ( ($nbitfield | $obitfield) & Revision::DELETED_RESTRICTED ) ?
                        'suppress' : 'delete';
-               $log = new LogPage( $logtype );
+               // Log deletions show with a difference action message
+               $logAction = ( $param == 'logid' ) ? 'event' : 'revision';
+               // Track what items changed here
                $itemCSV = implode(',',$items);
-
+               // Add params for effected page and ids
                if( $param == 'logid' ) {
                        $params = array( $itemCSV, "ofield={$obitfield}", "nfield={$nbitfield}" );
-                       $log->addEntry( 'event', $title, $comment, $params );
                } else {
-                       // Add params for effected page and ids
                        $params = array( $param, $itemCSV, "ofield={$obitfield}", "nfield={$nbitfield}" );
-                       $log->addEntry( 'revision', $title, $comment, $params );
                }
+               // Actually add the deletion log entry
+               $log = new LogPage( $logType );
+               $logid = $log->addEntry( $logAction, $title, $comment, $params );
+               // Allow for easy searching of deletion log items for revision/log items
+               $log->addRelations( self::getRelationType($param), $items, $logid );
        }
-}
+       
+       // Get DB field name for URL param...
+       // Future code for other things may also track
+       // other types of revision-specific changes.
+       public static function getRelationType( $param ) {
+               switch( $param ) {
+                       case 'oldid':
+                               return 'rev_id';
+                       case 'artimestamp':
+                               return 'rev_timestamp';
+                       case 'oldimage':
+                               return 'oi_timestamp';
+                       case 'fileid':
+                               return 'file_id';
+                       case 'logid':
+                               return 'log_id';
+               }
+               throw new MWException( "Bad log URL param type!" );
+       }
+}
\ No newline at end of file
diff --git a/maintenance/populateLogSearch.php b/maintenance/populateLogSearch.php
new file mode 100644 (file)
index 0000000..88127bf
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Makes the required database updates for Special:ProtectedPages
+ * to show all protected pages, even ones before the page restrictions
+ * schema change. All remaining page_restriction column values are moved
+ * to the new table.
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+define( 'BATCH_SIZE', 100 );
+
+require_once 'commandLine.inc';
+       
+$db =& wfGetDB( DB_MASTER );
+if ( !$db->tableExists( 'log_search' ) ) {
+       echo "log_search does not exist\n";
+       exit( 1 );
+}
+
+migrate_log_params( $db );
+
+function migrate_log_params( $db ) {
+       $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ );
+       if( !$start ) {
+               die("Nothing to do.\n");
+       }
+       $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ );
+       
+       # Do remaining chunk
+       $end += BATCH_SIZE - 1;
+       $blockStart = $start;
+       $blockEnd = $start + BATCH_SIZE - 1;
+       while( $blockEnd <= $end ) {
+               echo "...doing log_id from $blockStart to $blockEnd\n";
+               $cond = "log_id BETWEEN $blockStart AND $blockEnd";
+               $res = $db->select( 'logging', '*', $cond, __FUNCTION__ );
+               $batch = array();
+               while( $row = $db->fetchObject( $res ) ) {
+                       // RevisionDelete logs - revisions
+                       if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) {
+                               $params = LogPage::extractParams( $row->log_params );
+                               // Param format: <urlparam> <item CSV> [<ofield> <nfield>]
+                               if( count($params) >= 2 ) {
+                                       $field = RevisionDeleter::getRelationType($params[0]);
+                                       $items = explode(',',$params[1]);
+                                       $log = new LogPage( $row->log_type );
+                                       $log->addRelations( $field, $items, $row->log_id );
+                               }
+                       // RevisionDelete logs - log events
+                       } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) {
+                               $params = LogPage::extractParams( $row->log_params );
+                               // Param format: <item CSV> [<ofield> <nfield>]
+                               if( count($params) >= 1 ) {
+                                       $items = explode(',',$params[0]);
+                                       $log = new LogPage( $row->log_type );
+                                       $log->addRelations( 'log_id', $items, $row->log_id );
+                               }
+                       }
+               }
+               $blockStart += BATCH_SIZE - 1;
+               $blockEnd += BATCH_SIZE - 1;
+               wfWaitForSlaves( 5 );
+       }
+       echo "...Done!\n";
+}
index 80ff0aa..101a177 100644 (file)
@@ -1124,6 +1124,18 @@ CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_times
 CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp);
 
 
+CREATE TABLE /*_*/log_search (
+       -- The type of ID (rev ID, log ID, rev timestamp, username)
+       ls_field varbinary(32) NOT NULL,
+       -- The value of the ID
+       ls_value varchar(255) NOT NULL,
+       -- Key to log_id
+       ls_log_id int unsigned NOT NULL default 0,
+       PRIMARY KEY (ls_field,ls_value,ls_log_id)
+);
+CREATE INDEX /*i*/ls_log_id ON /*_*/log_search (ls_log_id);
+
+
 CREATE TABLE /*_*/trackbacks (
   tb_id int PRIMARY KEY AUTO_INCREMENT,
   tb_page int REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
index b404e9f..69db8bf 100644 (file)
@@ -156,6 +156,7 @@ $wgUpdates = array(
                array( 'add_table', 'tag_summary',                         'patch-change_tag.sql' ),
                array( 'add_table', 'valid_tag',                           'patch-change_tag.sql' ),
                array( 'add_table', 'user_properties',             'patch-user_properties.sql' ),
+               array( 'add_table', 'log_search',                          'patch-log_search.sql' ),
        ),
 
        'sqlite' => array(