Index: trunk/phase3/maintenance/updaters.inc |
— | — | @@ -156,6 +156,7 @@ |
157 | 157 | array( 'add_table', 'tag_summary', 'patch-change_tag.sql' ), |
158 | 158 | array( 'add_table', 'valid_tag', 'patch-change_tag.sql' ), |
159 | 159 | array( 'add_table', 'user_properties', 'patch-user_properties.sql' ), |
| 160 | + array( 'add_table', 'log_search', 'patch-log_search.sql' ), |
160 | 161 | ), |
161 | 162 | |
162 | 163 | 'sqlite' => array( |
Index: trunk/phase3/maintenance/populateLogSearch.php |
— | — | @@ -0,0 +1,67 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Makes the required database updates for Special:ProtectedPages |
| 5 | + * to show all protected pages, even ones before the page restrictions |
| 6 | + * schema change. All remaining page_restriction column values are moved |
| 7 | + * to the new table. |
| 8 | + * |
| 9 | + * @file |
| 10 | + * @ingroup Maintenance |
| 11 | + */ |
| 12 | + |
| 13 | +define( 'BATCH_SIZE', 100 ); |
| 14 | + |
| 15 | +require_once 'commandLine.inc'; |
| 16 | + |
| 17 | +$db =& wfGetDB( DB_MASTER ); |
| 18 | +if ( !$db->tableExists( 'log_search' ) ) { |
| 19 | + echo "log_search does not exist\n"; |
| 20 | + exit( 1 ); |
| 21 | +} |
| 22 | + |
| 23 | +migrate_log_params( $db ); |
| 24 | + |
| 25 | +function migrate_log_params( $db ) { |
| 26 | + $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ ); |
| 27 | + if( !$start ) { |
| 28 | + die("Nothing to do.\n"); |
| 29 | + } |
| 30 | + $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ ); |
| 31 | + |
| 32 | + # Do remaining chunk |
| 33 | + $end += BATCH_SIZE - 1; |
| 34 | + $blockStart = $start; |
| 35 | + $blockEnd = $start + BATCH_SIZE - 1; |
| 36 | + while( $blockEnd <= $end ) { |
| 37 | + echo "...doing log_id from $blockStart to $blockEnd\n"; |
| 38 | + $cond = "log_id BETWEEN $blockStart AND $blockEnd"; |
| 39 | + $res = $db->select( 'logging', '*', $cond, __FUNCTION__ ); |
| 40 | + $batch = array(); |
| 41 | + while( $row = $db->fetchObject( $res ) ) { |
| 42 | + // RevisionDelete logs - revisions |
| 43 | + if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) { |
| 44 | + $params = LogPage::extractParams( $row->log_params ); |
| 45 | + // Param format: <urlparam> <item CSV> [<ofield> <nfield>] |
| 46 | + if( count($params) >= 2 ) { |
| 47 | + $field = RevisionDeleter::getRelationType($params[0]); |
| 48 | + $items = explode(',',$params[1]); |
| 49 | + $log = new LogPage( $row->log_type ); |
| 50 | + $log->addRelations( $field, $items, $row->log_id ); |
| 51 | + } |
| 52 | + // RevisionDelete logs - log events |
| 53 | + } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) { |
| 54 | + $params = LogPage::extractParams( $row->log_params ); |
| 55 | + // Param format: <item CSV> [<ofield> <nfield>] |
| 56 | + if( count($params) >= 1 ) { |
| 57 | + $items = explode(',',$params[0]); |
| 58 | + $log = new LogPage( $row->log_type ); |
| 59 | + $log->addRelations( 'log_id', $items, $row->log_id ); |
| 60 | + } |
| 61 | + } |
| 62 | + } |
| 63 | + $blockStart += BATCH_SIZE - 1; |
| 64 | + $blockEnd += BATCH_SIZE - 1; |
| 65 | + wfWaitForSlaves( 5 ); |
| 66 | + } |
| 67 | + echo "...Done!\n"; |
| 68 | +} |
Property changes on: trunk/phase3/maintenance/populateLogSearch.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 69 | + native |
Index: trunk/phase3/maintenance/tables.sql |
— | — | @@ -1124,6 +1124,18 @@ |
1125 | 1125 | CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp); |
1126 | 1126 | |
1127 | 1127 | |
| 1128 | +CREATE TABLE /*_*/log_search ( |
| 1129 | + -- The type of ID (rev ID, log ID, rev timestamp, username) |
| 1130 | + ls_field varbinary(32) NOT NULL, |
| 1131 | + -- The value of the ID |
| 1132 | + ls_value varchar(255) NOT NULL, |
| 1133 | + -- Key to log_id |
| 1134 | + ls_log_id int unsigned NOT NULL default 0, |
| 1135 | + PRIMARY KEY (ls_field,ls_value,ls_log_id) |
| 1136 | +); |
| 1137 | +CREATE INDEX /*i*/ls_log_id ON /*_*/log_search (ls_log_id); |
| 1138 | + |
| 1139 | + |
1128 | 1140 | CREATE TABLE /*_*/trackbacks ( |
1129 | 1141 | tb_id int PRIMARY KEY AUTO_INCREMENT, |
1130 | 1142 | tb_page int REFERENCES /*_*/page(page_id) ON DELETE CASCADE, |
Index: trunk/phase3/includes/LogEventsList.php |
— | — | @@ -651,22 +651,29 @@ |
652 | 652 | } |
653 | 653 | |
654 | 654 | public function getQueryInfo() { |
| 655 | + $tables = array( 'logging', 'user' ); |
655 | 656 | $this->mConds[] = 'user_id = log_user'; |
| 657 | + $index = array(); |
| 658 | + # Add log_search table if there are conditions on it |
| 659 | + if( array_key_exists('ls_field',$this->mConds) ) { |
| 660 | + $tables[] = 'log_search'; |
| 661 | + $index = array( 'log_search' => 'PRIMARY', 'logging' => 'PRIMARY' ); |
656 | 662 | # Don't use the wrong logging index |
657 | | - if( $this->title || $this->pattern || $this->user ) { |
658 | | - $index = array( 'USE INDEX' => array( 'logging' => array('page_time','user_time') ) ); |
| 663 | + } else if( $this->title || $this->pattern || $this->user ) { |
| 664 | + $index = array( 'logging' => array('page_time','user_time') ); |
659 | 665 | } else if( $this->types ) { |
660 | | - $index = array( 'USE INDEX' => array( 'logging' => 'type_time' ) ); |
| 666 | + $index = array( 'logging' => 'type_time' ); |
661 | 667 | } else { |
662 | | - $index = array( 'USE INDEX' => array( 'logging' => 'times' ) ); |
| 668 | + $index = array( 'logging' => 'times' ); |
663 | 669 | } |
664 | 670 | $info = array( |
665 | | - 'tables' => array( 'logging', 'user' ), |
| 671 | + 'tables' => $tables, |
666 | 672 | 'fields' => array( 'log_type', 'log_action', 'log_user', 'log_namespace', 'log_title', 'log_params', |
667 | 673 | 'log_comment', 'log_id', 'log_deleted', 'log_timestamp', 'user_name', 'user_editcount' ), |
668 | 674 | 'conds' => $this->mConds, |
669 | | - 'options' => $index, |
670 | | - 'join_conds' => array( 'user' => array( 'INNER JOIN', 'user_id=log_user' ) ), |
| 675 | + 'options' => array( 'USE INDEX' => $index ), |
| 676 | + 'join_conds' => array( 'user' => array( 'INNER JOIN', 'user_id=log_user' ), |
| 677 | + 'log_search' => array( 'INNER JOIN', 'ls_log_id=log_id' ) ), |
671 | 678 | ); |
672 | 679 | |
673 | 680 | ChangeTags::modifyDisplayQuery( $info['tables'], $info['fields'], $info['conds'], |
Index: trunk/phase3/includes/specials/SpecialRevisiondelete.php |
— | — | @@ -85,16 +85,15 @@ |
86 | 86 | $this->showImages(); |
87 | 87 | } else if( $this->deleteKey == 'logid' ) { |
88 | 88 | $this->showLogItems(); |
89 | | - return; // no logs for now |
90 | 89 | } |
91 | | - list($qc,$lim) = $this->getLogQueryCond(); |
| 90 | + $qc = $this->getLogQueryCond(); |
92 | 91 | # Show relevant lines from the deletion log |
93 | 92 | $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'delete' ) ) . "</h2>\n" ); |
94 | | - LogEventsList::showLogExtract( $wgOut, 'delete', $this->page->getPrefixedText(), '', $lim, $qc ); |
| 93 | + LogEventsList::showLogExtract( $wgOut, 'delete', $this->page->getPrefixedText(), '', 25, $qc ); |
95 | 94 | # Show relevant lines from the suppression log |
96 | 95 | if( $wgUser->isAllowed( 'suppressionlog' ) ) { |
97 | 96 | $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'suppress' ) ) . "</h2>\n" ); |
98 | | - LogEventsList::showLogExtract( $wgOut, 'suppress', $this->page->getPrefixedText(), '', $lim, $qc ); |
| 97 | + LogEventsList::showLogExtract( $wgOut, 'suppress', $this->page->getPrefixedText(), '', 25, $qc ); |
99 | 98 | } |
100 | 99 | } |
101 | 100 | |
— | — | @@ -121,9 +120,7 @@ |
122 | 121 | } |
123 | 122 | |
124 | 123 | private function getLogQueryCond() { |
125 | | - $ids = $safeIds = array(); |
126 | | - $limit = 25; // default |
127 | | - $conds = array( 'log_action' => 'revision' ); // revision delete logs |
| 124 | + $logAction = 'revision'; |
128 | 125 | switch( $this->deleteKey ) { |
129 | 126 | case 'oldid': |
130 | 127 | $ids = $this->oldids; |
— | — | @@ -137,25 +134,19 @@ |
138 | 135 | case 'fileid': |
139 | 136 | $ids = $this->fileids; |
140 | 137 | break; |
| 138 | + case 'logid': |
| 139 | + $ids = $this->logids; |
| 140 | + $logAction = 'event'; |
| 141 | + break; |
141 | 142 | default: // bad type? |
142 | | - return array($conds,$limit); |
| 143 | + return array(); |
143 | 144 | } |
144 | | - // Just get the whole log if there are a lot if items |
145 | | - if( count($ids) > $limit ) |
146 | | - return array($conds,$limit); |
147 | | - // Digit chars only |
148 | | - foreach( $ids as $id ) { |
149 | | - if( preg_match( '/^\d+$/', $id, $m ) ) { |
150 | | - $safeIds[] = $m[0]; |
151 | | - } |
152 | | - } |
153 | | - // Format is <id1,id2,i3...> |
154 | | - if( count($safeIds) ) { |
155 | | - $conds[] = "log_params RLIKE '^{$this->deleteKey}.*(^|\n|,)(".implode('|',$safeIds).")(,|\n|$)'"; |
156 | | - } else { |
157 | | - $conds = array('1=0'); |
158 | | - } |
159 | | - return array($conds,$limit); |
| 145 | + // Revision delete logs for these item |
| 146 | + $conds = array( 'log_action' => $logAction ); |
| 147 | + $conds['ls_field'] = RevisionDeleter::getRelationType( $this->deleteKey ); |
| 148 | + $conds['ls_value'] = $ids; |
| 149 | + $conds[] = 'log_id = ls_log_id'; |
| 150 | + return $conds; |
160 | 151 | } |
161 | 152 | |
162 | 153 | private function secureOperation() { |
— | — | @@ -824,7 +815,7 @@ |
825 | 816 | |
826 | 817 | private function failure() { |
827 | 818 | global $wgOut; |
828 | | - $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) ); |
| 819 | + $wgOut->setPagetitle( wfMsg( 'actionfailed' ) ); |
829 | 820 | $wrap = '<span class="error">$1</span>'; |
830 | 821 | if( $this->deleteKey == 'logid' ) { |
831 | 822 | $this->showLogItems(); |
— | — | @@ -1540,18 +1531,41 @@ |
1541 | 1532 | $param, $items = array() ) |
1542 | 1533 | { |
1543 | 1534 | // Put things hidden from sysops in the oversight log |
1544 | | - $logtype = ( ($nbitfield | $obitfield) & Revision::DELETED_RESTRICTED ) ? |
| 1535 | + $logType = ( ($nbitfield | $obitfield) & Revision::DELETED_RESTRICTED ) ? |
1545 | 1536 | 'suppress' : 'delete'; |
1546 | | - $log = new LogPage( $logtype ); |
| 1537 | + // Log deletions show with a difference action message |
| 1538 | + $logAction = ( $param == 'logid' ) ? 'event' : 'revision'; |
| 1539 | + // Track what items changed here |
1547 | 1540 | $itemCSV = implode(',',$items); |
1548 | | - |
| 1541 | + // Add params for effected page and ids |
1549 | 1542 | if( $param == 'logid' ) { |
1550 | 1543 | $params = array( $itemCSV, "ofield={$obitfield}", "nfield={$nbitfield}" ); |
1551 | | - $log->addEntry( 'event', $title, $comment, $params ); |
1552 | 1544 | } else { |
1553 | | - // Add params for effected page and ids |
1554 | 1545 | $params = array( $param, $itemCSV, "ofield={$obitfield}", "nfield={$nbitfield}" ); |
1555 | | - $log->addEntry( 'revision', $title, $comment, $params ); |
1556 | 1546 | } |
| 1547 | + // Actually add the deletion log entry |
| 1548 | + $log = new LogPage( $logType ); |
| 1549 | + $logid = $log->addEntry( $logAction, $title, $comment, $params ); |
| 1550 | + // Allow for easy searching of deletion log items for revision/log items |
| 1551 | + $log->addRelations( self::getRelationType($param), $items, $logid ); |
1557 | 1552 | } |
1558 | | -} |
| 1553 | + |
| 1554 | + // Get DB field name for URL param... |
| 1555 | + // Future code for other things may also track |
| 1556 | + // other types of revision-specific changes. |
| 1557 | + public static function getRelationType( $param ) { |
| 1558 | + switch( $param ) { |
| 1559 | + case 'oldid': |
| 1560 | + return 'rev_id'; |
| 1561 | + case 'artimestamp': |
| 1562 | + return 'rev_timestamp'; |
| 1563 | + case 'oldimage': |
| 1564 | + return 'oi_timestamp'; |
| 1565 | + case 'fileid': |
| 1566 | + return 'file_id'; |
| 1567 | + case 'logid': |
| 1568 | + return 'log_id'; |
| 1569 | + } |
| 1570 | + throw new MWException( "Bad log URL param type!" ); |
| 1571 | + } |
| 1572 | +} |
\ No newline at end of file |
Index: trunk/phase3/includes/LogPage.php |
— | — | @@ -91,7 +91,7 @@ |
92 | 92 | $this->type, $this->action, $this->target, $this->comment, $this->params, $newId ); |
93 | 93 | $rc->notifyRC2UDP(); |
94 | 94 | } |
95 | | - return true; |
| 95 | + return $newId; |
96 | 96 | } |
97 | 97 | |
98 | 98 | /** |
— | — | @@ -373,6 +373,22 @@ |
374 | 374 | |
375 | 375 | return $this->saveContent(); |
376 | 376 | } |
| 377 | + |
| 378 | + /** |
| 379 | + * Add relations to log_search table |
| 380 | + * @static |
| 381 | + */ |
| 382 | + public function addRelations( $field, $values, $logid ) { |
| 383 | + if( empty($values) ) |
| 384 | + return false; // nothing |
| 385 | + $data = array(); |
| 386 | + foreach( $values as $value ) { |
| 387 | + $data[] = array('ls_field' => $field,'ls_value' => $value,'ls_log_id' => $logid); |
| 388 | + } |
| 389 | + $dbw = wfGetDB( DB_MASTER ); |
| 390 | + $dbw->insert( 'log_search', $data, __METHOD__, 'IGNORE' ); |
| 391 | + return true; |
| 392 | + } |
377 | 393 | |
378 | 394 | /** |
379 | 395 | * Create a blob from a parameter array |