$html .= $this->getTypeMenu( $types ) . "\n";
$html .= $this->getUserInput( $user ) . "\n";
$html .= $this->getTitleInput( $page ) . "\n";
+ $html .= $this->getExtraInputs( $types ) . "\n";
// Title pattern, if allowed
if (!$wgMiserMode) {
Xml::checkLabel( wfMsg( 'log-title-wildcard' ), 'pattern', 'pattern', $pattern ) .
'</span>';
}
+
+ private function getExtraInputs( $types ) {
+ global $wgRequest;
+ if( count($types) == 1 && $types[0] == 'suppress' ) {
+ return Xml::inputLabel( wfMsg('revdelete-offender'), 'offender',
+ 'mw-log-offender', 20, $wgRequest->getVal('offender') );
+ }
+ return '';
+ }
public function beginLogEventsList() {
return "<ul>\n";
$y = '';
$m = '';
}
+ # Handle type-specific inputs
+ $qc = array();
+ if( $type == 'suppress' ) {
+ $offender = User::newFromName( $wgRequest->getVal('offender'), false );
+ if( $offender && $offender->getId() > 0 ) {
+ $qc = array( 'ls_field' => 'target_author_id', 'ls_value' => $offender->getId() );
+ } else if( $offender && IP::isIPAddress( $offender->getName() ) ) {
+ $qc = array( 'ls_field' => 'target_author_ip', 'ls_value' => $offender->getName() );
+ }
+ }
# Create a LogPager item to get the results and a LogEventsList item to format them...
$loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, 0 );
- $pager = new LogPager( $loglist, $type, $user, $title, $pattern, array(), $y, $m, $tagFilter );
+ $pager = new LogPager( $loglist, $type, $user, $title, $pattern, $qc, $y, $m, $tagFilter );
# Set title and add header
$loglist->showHeader( $pager->getType() );
# Show form options
# Give a link to the logs/hist for this page
if( $this->targetObj ) {
$links = array();
- $logtitle = SpecialPage::getTitleFor( 'Log' );
$links[] = $this->skin->linkKnown(
- $logtitle,
+ SpecialPage::getTitleFor( 'Log' ),
wfMsgHtml( 'viewpagelogs' ),
array(),
array( 'page' => $this->targetObj->getPrefixedText() )
// Get DB field name for URL param...
// Future code for other things may also track
// other types of revision-specific changes.
+ // @returns string One of log_id/rev_id/fa_id/ar_timestamp/oi_archive_name
public static function getRelationType( $typeName ) {
if ( isset( SpecialRevisionDelete::$deprecatedTypeMap[$typeName] ) ) {
$typeName = SpecialRevisionDelete::$deprecatedTypeMap[$typeName];
var $type = null; // override this
var $idField = null; // override this
var $dateField = false; // override this
+ var $authorIdField = false; // override this
+ var $authorNameField = false; // override this
/**
* @param $special The parent SpecialPage
}
/**
- * Get the DB field name associated with the ID list/
+ * Get the DB field name associated with the ID list
*/
public function getIdField() {
return $this->idField;
return $this->dateField;
}
+ /**
+ * Get the DB field name storing user ids
+ */
+ public function getAuthorIdField() {
+ return $this->authorIdField;
+ }
+
+ /**
+ * Get the DB field name storing user names
+ */
+ public function getAuthorNameField() {
+ return $this->authorNameField;
+ }
/**
* Set the visibility for the revisions in this list. Logging and
* transactions are done here.
$missing = array_flip( $this->ids );
$this->clearFileOps();
$idsForLog = array();
+ $authorIds = $authorIPs = array();
for ( $this->reset(); $this->current(); $this->next() ) {
$item = $this->current();
if ( $ok ) {
$idsForLog[] = $item->getId();
$status->successCount++;
+ if( $item->getAuthorId() > 0 ) {
+ $authorIds[] = $item->getAuthorId();
+ } else if( IP::isIPAddress( $item->getAuthorName() ) ) {
+ $authorIPs[] = $item->getAuthorName();
+ }
} else {
$status->error( 'revdelete-concurrent-change', $item->formatDate(), $item->formatTime() );
$status->failCount++;
'oldBits' => $oldBits,
'comment' => $comment,
'ids' => $idsForLog,
+ 'authorIds' => $authorIds,
+ 'authorIPs' => $authorIPs
) );
$dbw->commit();
* title: The target title
* ids: The ID list
* comment: The log comment
+ * authorsIds: The array of the user IDs of the offenders
+ * authorsIPs: The array of the IP/anon user offenders
*/
protected function updateLog( $params ) {
// Get the URL param's corresponding DB field
$params['comment'], $logParams );
// Allow for easy searching of deletion log items for revision/log items
$log->addRelations( $field, $params['ids'], $logid );
+ $log->addRelations( 'target_author_id', $params['authorIds'], $logid );
+ $log->addRelations( 'target_author_ip', $params['authorIPs'], $logid );
}
/**
$field = $this->list->getTimestampField();
return wfTimestamp( TS_MW, $this->row->$field );
}
+
+ /**
+ * Get the author user ID
+ */
+ public function getAuthorId() {
+ $field = $this->list->getAuthorIdField();
+ return intval( $this->row->$field );
+ }
+
+ /**
+ * Get the author user name
+ */
+ public function getAuthorName() {
+ $field = $this->list->getAuthorNameField();
+ return strval( $this->row->$field );
+ }
/**
* Returns true if the item is "current", and the operation to set the given
var $type = 'revision';
var $idField = 'rev_id';
var $dateField = 'rev_timestamp';
+ var $authorIdField = 'rev_user';
+ var $authorNameField = 'rev_user_text';
public function doQuery( $db ) {
$ids = array_map( 'intval', $this->ids );
var $type = 'archive';
var $idField = 'ar_timestamp';
var $dateField = 'ar_timestamp';
+ var $authorIdField = 'ar_user';
+ var $authorNameField = 'ar_user_text';
public function doQuery( $db ) {
$timestamps = array();
var $type = 'oldimage';
var $idField = 'oi_archive_name';
var $dateField = 'oi_timestamp';
+ var $authorIdField = 'oi_user';
+ var $authorNameField = 'oi_user_text';
var $storeBatch, $deleteBatch, $cleanupBatch;
public function doQuery( $db ) {
var $type = 'filearchive';
var $idField = 'fa_id';
var $dateField = 'fa_timestamp';
+ var $authorIdField = 'fa_user';
+ var $authorNameField = 'fa_user_text';
public function doQuery( $db ) {
$ids = array_map( 'intval', $this->ids );
var $type = 'logging';
var $idField = 'log_id';
var $dateField = 'log_timestamp';
+ var $authorIdField = 'log_user';
+ var $authorNameField = 'log_user_text';
public function doQuery( $db ) {
global $wgMessageCache;
),
array(
'rc_logid' => $this->row->log_id,
- 'rc_timestamp' => $this->row->log_timestamp
+ 'rc_timestamp' => $this->row->log_timestamp // index
),
__METHOD__
);
$paramArray = LogPage::extractParams( $this->row->log_params );
$title = Title::makeTitle( $this->row->log_namespace, $this->row->log_title );
- $logtitle = SpecialPage::getTitleFor( 'Log' );
+ // Log link for this page
$loglink = $this->special->skin->link(
- $logtitle,
+ SpecialPage::getTitleFor( 'Log' ),
wfMsgHtml( 'log' ),
array(),
array( 'page' => $title->getPrefixedText() )
'revdelete-otherreason' => 'Other/additional reason:',
'revdelete-reasonotherlist' => 'Other reason',
'revdelete-edit-reasonlist' => 'Edit delete reasons',
+'revdelete-offender' => 'Offender:',
# Suppression log
'suppressionlog' => 'Suppression log',
'revdelete-otherreason',
'revdelete-reasonotherlist',
'revdelete-edit-reasonlist',
+ 'revdelete-offender',
),
'suppression' => array(
'suppressionlog',
const LOG_SEARCH_BATCH_SIZE = 100;
+ static $tableMap = array('rev' => 'revision', 'fa' => 'filearchive', 'oi' => 'oldimage', 'ar' => 'archive');
+
public function __construct() {
parent::__construct();
$this->mDescription = "Migrate log params to new table and index for searching";
$end += self::LOG_SEARCH_BATCH_SIZE - 1;
$blockStart = $start;
$blockEnd = $start + self::LOG_SEARCH_BATCH_SIZE - 1;
+
+ $delTypes = array('delete','suppress'); // revisiondelete types
while( $blockEnd <= $end ) {
$this->output( "...doing log_id from $blockStart to $blockEnd\n" );
$cond = "log_id BETWEEN $blockStart AND $blockEnd";
$batch = array();
foreach( $res as $row ) {
// RevisionDelete logs - revisions
- if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) {
+ if( LogEventsList::typeAction( $row, $delTypes, 'revision' ) ) {
$params = LogPage::extractParams( $row->log_params );
// Param format: <urlparam> <item CSV> [<ofield> <nfield>]
- if( count($params) >= 2 ) {
+ if( count($params) < 2 ) continue; // bad row?
+ $field = RevisionDeleter::getRelationType($params[0]);
+ // B/C, the params may start with a title key (<title> <urlparam> <CSV>)
+ if( $field == null ) {
+ array_shift($params); // remove title param
$field = RevisionDeleter::getRelationType($params[0]);
- // B/C, the params may start with a title key
- if( $field == null ) {
- array_shift($params);
- $field = RevisionDeleter::getRelationType($params[0]);
- }
if( $field == null ) {
- $this->output( "Invalid param type for $row->log_id\n" );
+ $this->output( "Invalid param type for {$row->log_id}\n" );
continue; // skip this row
+ } else {
+ // Clean up the row...
+ $db->update( 'logging',
+ array('log_params' => implode(',',$params) ),
+ array('log_id' => $row->log_id ) );
}
- $items = explode(',',$params[1]);
- $log = new LogPage( $row->log_type );
- $log->addRelations( $field, $items, $row->log_id );
}
+ $items = explode(',',$params[1]);
+ $log = new LogPage( $row->log_type );
+ // Add item relations...
+ $log->addRelations( $field, $items, $row->log_id );
+ // Determine what table to query...
+ $prefix = substr( $field, 0, strpos($field,'_') ); // db prefix
+ if( !isset(self::$tableMap[$prefix]) )
+ continue; // bad row?
+ $table = self::$tableMap[$prefix];
+ $userField = $prefix.'_user';
+ $userTextField = $prefix.'_user_text';
+ // Add item author relations...
+ $userIds = $userIPs = array();
+ $sres = $db->select( $table,
+ array($userField,$userTextField),
+ array($field => $items)
+ );
+ foreach( $sres as $srow ) {
+ if( $srow->$userField > 0 )
+ $userIds[] = intval($srow->$userField);
+ else if( $srow->$userTextField != '' )
+ $userIPs[] = $srow->$userTextField;
+ }
+ // Add item author relations...
+ $log->addRelations( 'target_author_id', $userIds, $row->log_id );
+ $log->addRelations( 'target_author_ip', $userIPs, $row->log_id );
// RevisionDelete logs - log events
- } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) {
+ } else if( LogEventsList::typeAction( $row, $delTypes, '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 );
+ if( count($params) < 1 ) continue; // bad row
+ $items = explode( ',', $params[0] );
+ $log = new LogPage( $row->log_type );
+ // Add item relations...
+ $log->addRelations( 'log_id', $items, $row->log_id );
+ // Add item author relations...
+ $userIds = $userIPs = array();
+ $sres = $db->select( 'logging',
+ array('log_user','log_user_text'),
+ array('log_id' => $items)
+ );
+ foreach( $sres as $srow ) {
+ if( $srow->log_user > 0 )
+ $userIds[] = intval($srow->log_user);
+ else if( IP::isIPAddress($srow->log_user_text) )
+ $userIPs[] = $srow->log_user_text;
}
+ $log->addRelations( 'target_author_id', $userIds, $row->log_id );
+ $log->addRelations( 'target_author_ip', $userIPs, $row->log_id );
}
}
$blockStart += self::LOG_SEARCH_BATCH_SIZE;