From ca32f08966f1b51fcb19460f0996bb0c4048e6fe Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Sat, 3 Dec 2011 13:29:22 +0100 Subject: Update to MediaWiki 1.18.0 * also update ArchLinux skin to chagnes in MonoBook * Use only css to hide our menu bar when printing --- includes/revisiondelete/RevisionDelete.php | 374 ++++++++++++++++----- .../revisiondelete/RevisionDeleteAbstracts.php | 235 ++----------- includes/revisiondelete/RevisionDeleteUser.php | 130 +++++++ includes/revisiondelete/RevisionDeleter.php | 191 ++++------- 4 files changed, 505 insertions(+), 425 deletions(-) create mode 100644 includes/revisiondelete/RevisionDeleteUser.php (limited to 'includes/revisiondelete') diff --git a/includes/revisiondelete/RevisionDelete.php b/includes/revisiondelete/RevisionDelete.php index 00afb053..b329fc4b 100644 --- a/includes/revisiondelete/RevisionDelete.php +++ b/includes/revisiondelete/RevisionDelete.php @@ -1,18 +1,31 @@ ids ); - return $db->select( array('revision','page'), '*', + $live = $db->select( array('revision','page'), '*', array( 'rev_page' => $this->title->getArticleID(), 'rev_id' => $ids, @@ -21,16 +34,54 @@ class RevDel_RevisionList extends RevDel_List { __METHOD__, array( 'ORDER BY' => 'rev_id DESC' ) ); + + if ( $live->numRows() >= count( $ids ) ) { + // All requested revisions are live, keeps things simple! + return $live; + } + + // Check if any requested revisions are available fully deleted. + $archived = $db->select( array( 'archive' ), '*', + array( + 'ar_rev_id' => $ids + ), + __METHOD__, + array( 'ORDER BY' => 'ar_rev_id DESC' ) + ); + + if ( $archived->numRows() == 0 ) { + return $live; + } elseif ( $live->numRows() == 0 ) { + return $archived; + } else { + // Combine the two! Whee + $rows = array(); + foreach ( $live as $row ) { + $rows[$row->rev_id] = $row; + } + foreach ( $archived as $row ) { + $rows[$row->ar_rev_id] = $row; + } + krsort( $rows ); + return new FakeResultWrapper( array_values( $rows ) ); + } } public function newItem( $row ) { - return new RevDel_RevisionItem( $this, $row ); + if ( isset( $row->rev_id ) ) { + return new RevDel_RevisionItem( $this, $row ); + } elseif ( isset( $row->ar_rev_id ) ) { + return new RevDel_ArchivedRevisionItem( $this, $row ); + } else { + // This shouldn't happen. :) + throw new MWException( 'Invalid row type in RevDel_RevisionList' ); + } } public function getCurrent() { if ( is_null( $this->currentRevId ) ) { $dbw = wfGetDB( DB_MASTER ); - $this->currentRevId = $dbw->selectField( + $this->currentRevId = $dbw->selectField( 'page', 'page_latest', $this->title->pageCond(), __METHOD__ ); } return $this->currentRevId; @@ -54,7 +105,7 @@ class RevDel_RevisionList extends RevDel_List { } /** - * Item class for a revision table row + * Item class for a live revision table row */ class RevDel_RevisionItem extends RevDel_Item { var $revision; @@ -64,10 +115,26 @@ class RevDel_RevisionItem extends RevDel_Item { $this->revision = new Revision( $row ); } + public function getIdField() { + return 'rev_id'; + } + + public function getTimestampField() { + return 'rev_timestamp'; + } + + public function getAuthorIdField() { + return 'rev_user'; + } + + public function getAuthorNameField() { + return 'rev_user_text'; + } + public function canView() { return $this->revision->userCan( Revision::DELETED_RESTRICTED ); } - + public function canViewContent() { return $this->revision->userCan( Revision::DELETED_TEXT ); } @@ -81,8 +148,8 @@ class RevDel_RevisionItem extends RevDel_Item { // Update revision table $dbw->update( 'revision', array( 'rev_deleted' => $bits ), - array( - 'rev_id' => $this->revision->getId(), + array( + 'rev_id' => $this->revision->getId(), 'rev_page' => $this->revision->getPage(), 'rev_deleted' => $this->getBits() ), @@ -94,7 +161,7 @@ class RevDel_RevisionItem extends RevDel_Item { } // Update recentchanges table $dbw->update( 'recentchanges', - array( + array( 'rc_deleted' => $bits, 'rc_patrolled' => 1 ), @@ -113,7 +180,7 @@ class RevDel_RevisionItem extends RevDel_Item { } public function isHideCurrentOp( $newBits ) { - return ( $newBits & Revision::DELETED_TEXT ) + return ( $newBits & Revision::DELETED_TEXT ) && $this->list->getCurrent() == $this->getId(); } @@ -122,14 +189,13 @@ class RevDel_RevisionItem extends RevDel_Item { * Overridden by RevDel_ArchiveItem. */ protected function getRevisionLink() { - global $wgLang; - $date = $wgLang->timeanddate( $this->revision->getTimestamp(), true ); + $date = $this->list->getLang()->timeanddate( $this->revision->getTimestamp(), true ); if ( $this->isDeleted() && !$this->canViewContent() ) { return $date; } - return $this->special->skin->link( + return Linker::link( $this->list->title, - $date, + $date, array(), array( 'oldid' => $this->revision->getId(), @@ -146,9 +212,9 @@ class RevDel_RevisionItem extends RevDel_Item { if ( $this->isDeleted() && !$this->canViewContent() ) { return wfMsgHtml('diff'); } else { - return - $this->special->skin->link( - $this->list->title, + return + Linker::link( + $this->list->title, wfMsgHtml('diff'), array(), array( @@ -167,8 +233,8 @@ class RevDel_RevisionItem extends RevDel_Item { public function getHTML() { $difflink = $this->getDiffLink(); $revlink = $this->getRevisionLink(); - $userlink = $this->special->skin->revUserLink( $this->revision ); - $comment = $this->special->skin->revComment( $this->revision ); + $userlink = Linker::revUserLink( $this->revision ); + $comment = Linker::revComment( $this->revision ); if ( $this->isDeleted() ) { $revlink = "$revlink"; } @@ -180,12 +246,18 @@ class RevDel_RevisionItem extends RevDel_Item { * List for archive table items, i.e. revisions deleted via action=delete */ class RevDel_ArchiveList extends RevDel_RevisionList { - var $type = 'archive'; - var $idField = 'ar_timestamp'; - var $dateField = 'ar_timestamp'; - var $authorIdField = 'ar_user'; - var $authorNameField = 'ar_user_text'; + public function getType() { + return 'archive'; + } + + public static function getRelationType() { + return 'ar_timestamp'; + } + /** + * @param $db DatabaseBase + * @return mixed + */ public function doQuery( $db ) { $timestamps = array(); foreach ( $this->ids as $id ) { @@ -225,34 +297,50 @@ class RevDel_ArchiveItem extends RevDel_RevisionItem { array( 'page' => $this->list->title->getArticleId() ) ); } + public function getIdField() { + return 'ar_timestamp'; + } + + public function getTimestampField() { + return 'ar_timestamp'; + } + + public function getAuthorIdField() { + return 'ar_user'; + } + + public function getAuthorNameField() { + return 'ar_user_text'; + } + public function getId() { # Convert DB timestamp to MW timestamp return $this->revision->getTimestamp(); } - + public function setBits( $bits ) { $dbw = wfGetDB( DB_MASTER ); $dbw->update( 'archive', array( 'ar_deleted' => $bits ), - array( 'ar_namespace' => $this->list->title->getNamespace(), - 'ar_title' => $this->list->title->getDBkey(), + array( + 'ar_namespace' => $this->list->title->getNamespace(), + 'ar_title' => $this->list->title->getDBkey(), // use timestamp for index - 'ar_timestamp' => $this->row->ar_timestamp, - 'ar_rev_id' => $this->row->ar_rev_id, - 'ar_deleted' => $this->getBits() + 'ar_timestamp' => $this->row->ar_timestamp, + 'ar_rev_id' => $this->row->ar_rev_id, + 'ar_deleted' => $this->getBits() ), __METHOD__ ); return (bool)$dbw->affectedRows(); } protected function getRevisionLink() { - global $wgLang; $undelete = SpecialPage::getTitleFor( 'Undelete' ); - $date = $wgLang->timeanddate( $this->revision->getTimestamp(), true ); + $date = $this->list->getLang()->timeanddate( $this->revision->getTimestamp(), true ); if ( $this->isDeleted() && !$this->canViewContent() ) { return $date; } - return $this->special->skin->link( $undelete, $date, array(), + return Linker::link( $undelete, $date, array(), array( 'target' => $this->list->title->getPrefixedText(), 'timestamp' => $this->revision->getTimestamp() @@ -263,8 +351,8 @@ class RevDel_ArchiveItem extends RevDel_RevisionItem { if ( $this->isDeleted() && !$this->canViewContent() ) { return wfMsgHtml( 'diff' ); } - $undelete = SpecialPage::getTitleFor( 'Undelete' ); - return $this->special->skin->link( $undelete, wfMsgHtml('diff'), array(), + $undelete = SpecialPage::getTitleFor( 'Undelete' ); + return Linker::link( $undelete, wfMsgHtml('diff'), array(), array( 'target' => $this->list->title->getPrefixedText(), 'diff' => 'prev', @@ -273,17 +361,57 @@ class RevDel_ArchiveItem extends RevDel_RevisionItem { } } + +/** + * Item class for a archive table row by ar_rev_id -- actually + * used via RevDel_RevisionList. + */ +class RevDel_ArchivedRevisionItem extends RevDel_ArchiveItem { + public function __construct( $list, $row ) { + RevDel_Item::__construct( $list, $row ); + + $this->revision = Revision::newFromArchiveRow( $row, + array( 'page' => $this->list->title->getArticleId() ) ); + } + + public function getIdField() { + return 'ar_rev_id'; + } + + public function getId() { + return $this->revision->getId(); + } + + public function setBits( $bits ) { + $dbw = wfGetDB( DB_MASTER ); + $dbw->update( 'archive', + array( 'ar_deleted' => $bits ), + array( 'ar_rev_id' => $this->row->ar_rev_id, + 'ar_deleted' => $this->getBits() + ), + __METHOD__ ); + return (bool)$dbw->affectedRows(); + } +} + /** * List for oldimage table items */ class RevDel_FileList extends RevDel_List { - var $type = 'oldimage'; - var $idField = 'oi_archive_name'; - var $dateField = 'oi_timestamp'; - var $authorIdField = 'oi_user'; - var $authorNameField = 'oi_user_text'; + public function getType() { + return 'oldimage'; + } + + public static function getRelationType() { + return 'oi_archive_name'; + } + var $storeBatch, $deleteBatch, $cleanupBatch; + /** + * @param $db DatabaseBase + * @return mixed + */ public function doQuery( $db ) { $archiveNames = array(); foreach( $this->ids as $timestamp ) { @@ -348,6 +476,10 @@ class RevDel_FileList extends RevDel_List { * Item class for an oldimage table row */ class RevDel_FileItem extends RevDel_Item { + + /** + * @var File + */ var $file; public function __construct( $list, $row ) { @@ -355,6 +487,22 @@ class RevDel_FileItem extends RevDel_Item { $this->file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row ); } + public function getIdField() { + return 'oi_archive_name'; + } + + public function getTimestampField() { + return 'oi_timestamp'; + } + + public function getAuthorIdField() { + return 'oi_user'; + } + + public function getAuthorNameField() { + return 'oi_user_text'; + } + public function getId() { $parts = explode( '!', $this->row->oi_archive_name ); return $parts[0]; @@ -363,7 +511,7 @@ class RevDel_FileItem extends RevDel_Item { public function canView() { return $this->file->userCan( File::DELETED_RESTRICTED ); } - + public function canViewContent() { return $this->file->userCan( File::DELETED_FILE ); } @@ -374,7 +522,7 @@ class RevDel_FileItem extends RevDel_Item { public function setBits( $bits ) { # Queue the file op - # FIXME: move to LocalFile.php + # @todo FIXME: Move to LocalFile.php if ( $this->isDeleted() ) { if ( $bits & File::DELETED_FILE ) { # Still deleted @@ -395,12 +543,12 @@ class RevDel_FileItem extends RevDel_Item { $dstRel = $this->file->repo->getDeletedHashPath( $key ) . $key; $this->list->deleteBatch[] = array( $this->file->getRel(), $dstRel ); } - + # Do the database operations $dbw = wfGetDB( DB_MASTER ); $dbw->update( 'oldimage', array( 'oi_deleted' => $bits ), - array( + array( 'oi_name' => $this->row->oi_name, 'oi_timestamp' => $this->row->oi_timestamp, 'oi_deleted' => $this->getBits() @@ -415,24 +563,25 @@ class RevDel_FileItem extends RevDel_Item { } /** - * Get the link to the file. + * Get the link to the file. * Overridden by RevDel_ArchivedFileItem. */ protected function getLink() { - global $wgLang, $wgUser; - $date = $wgLang->timeanddate( $this->file->getTimestamp(), true ); + $date = $this->list->getLang()->timeanddate( $this->file->getTimestamp(), true ); if ( $this->isDeleted() ) { # Hidden files... if ( !$this->canViewContent() ) { $link = $date; } else { - $link = $this->special->skin->link( - $this->special->getTitle(), - $date, array(), + $revdelete = SpecialPage::getTitleFor( 'Revisiondelete' ); + $link = Linker::link( + $revdelete, + $date, array(), array( 'target' => $this->list->title->getPrefixedText(), 'file' => $this->file->getArchiveName(), - 'token' => $wgUser->editToken( $this->file->getArchiveName() ) + 'token' => $this->list->getUser()->editToken( + $this->file->getArchiveName() ) ) ); } @@ -448,8 +597,8 @@ class RevDel_FileItem extends RevDel_Item { */ protected function getUserTools() { if( $this->file->userCan( Revision::DELETED_USER ) ) { - $link = $this->special->skin->userLink( $this->file->user, $this->file->user_text ) . - $this->special->skin->userToolLinks( $this->file->user, $this->file->user_text ); + $link = Linker::userLink( $this->file->user, $this->file->user_text ) . + Linker::userToolLinks( $this->file->user, $this->file->user_text ); } else { $link = wfMsgHtml( 'rev-deleted-user' ); } @@ -467,7 +616,7 @@ class RevDel_FileItem extends RevDel_Item { */ protected function getComment() { if( $this->file->userCan( File::DELETED_COMMENT ) ) { - $block = $this->special->skin->commentBlock( $this->file->description ); + $block = Linker::commentBlock( $this->file->description ); } else { $block = ' ' . wfMsgHtml( 'rev-deleted-comment' ); } @@ -478,15 +627,14 @@ class RevDel_FileItem extends RevDel_Item { } public function getHTML() { - global $wgLang; - $data = + $data = wfMsg( - 'widthheight', - $wgLang->formatNum( $this->file->getWidth() ), - $wgLang->formatNum( $this->file->getHeight() ) + 'widthheight', + $this->list->getLang()->formatNum( $this->file->getWidth() ), + $this->list->getLang()->formatNum( $this->file->getHeight() ) ) . - ' (' . - wfMsgExt( 'nbytes', 'parsemag', $wgLang->formatNum( $this->file->getSize() ) ) . + ' (' . + wfMsgExt( 'nbytes', 'parsemag', $this->list->getLang()->formatNum( $this->file->getSize() ) ) . ')'; return '
  • ' . $this->getLink() . ' ' . $this->getUserTools() . ' ' . @@ -498,12 +646,18 @@ class RevDel_FileItem extends RevDel_Item { * List for filearchive table items */ class RevDel_ArchivedFileList extends RevDel_FileList { - var $type = 'filearchive'; - var $idField = 'fa_id'; - var $dateField = 'fa_timestamp'; - var $authorIdField = 'fa_user'; - var $authorNameField = 'fa_user_text'; - + public function getType() { + return 'filearchive'; + } + + public static function getRelationType() { + return 'fa_id'; + } + + /** + * @param $db DatabaseBase + * @return mixed + */ public function doQuery( $db ) { $ids = array_map( 'intval', $this->ids ); return $db->select( 'filearchive', '*', @@ -530,6 +684,22 @@ class RevDel_ArchivedFileItem extends RevDel_FileItem { $this->file = ArchivedFile::newFromRow( $row ); } + public function getIdField() { + return 'fa_id'; + } + + public function getTimestampField() { + return 'fa_timestamp'; + } + + public function getAuthorIdField() { + return 'fa_user'; + } + + public function getAuthorNameField() { + return 'fa_user_text'; + } + public function getId() { return $this->row->fa_id; } @@ -548,19 +718,18 @@ class RevDel_ArchivedFileItem extends RevDel_FileItem { } protected function getLink() { - global $wgLang, $wgUser; - $date = $wgLang->timeanddate( $this->file->getTimestamp(), true ); + $date = $this->list->getLang()->timeanddate( $this->file->getTimestamp(), true ); $undelete = SpecialPage::getTitleFor( 'Undelete' ); $key = $this->file->getKey(); # Hidden files... if( !$this->canViewContent() ) { $link = $date; } else { - $link = $this->special->skin->link( $undelete, $date, array(), + $link = Linker::link( $undelete, $date, array(), array( 'target' => $this->list->title->getPrefixedText(), 'file' => $key, - 'token' => $wgUser->editToken( $key ) + 'token' => $this->list->getUser()->editToken( $key ) ) ); } @@ -575,12 +744,18 @@ class RevDel_ArchivedFileItem extends RevDel_FileItem { * List for logging table items */ class RevDel_LogList extends RevDel_List { - var $type = 'logging'; - var $idField = 'log_id'; - var $dateField = 'log_timestamp'; - var $authorIdField = 'log_user'; - var $authorNameField = 'log_user_text'; + public function getType() { + return 'logging'; + } + + public static function getRelationType() { + return 'log_id'; + } + /** + * @param $db DatabaseBase + * @return mixed + */ public function doQuery( $db ) { $ids = array_map( 'intval', $this->ids ); return $db->select( 'logging', '*', @@ -615,10 +790,26 @@ class RevDel_LogList extends RevDel_List { * Item class for a logging table row */ class RevDel_LogItem extends RevDel_Item { + public function getIdField() { + return 'log_id'; + } + + public function getTimestampField() { + return 'log_timestamp'; + } + + public function getAuthorIdField() { + return 'log_user'; + } + + public function getAuthorNameField() { + return 'log_user_text'; + } + public function canView() { return LogEventsList::userCan( $this->row, Revision::DELETED_RESTRICTED ); } - + public function canViewContent() { return true; // none } @@ -630,9 +821,9 @@ class RevDel_LogItem extends RevDel_Item { public function setBits( $bits ) { $dbw = wfGetDB( DB_MASTER ); $dbw->update( 'recentchanges', - array( - 'rc_deleted' => $bits, - 'rc_patrolled' => 1 + array( + 'rc_deleted' => $bits, + 'rc_patrolled' => 1 ), array( 'rc_logid' => $this->row->log_id, @@ -652,14 +843,12 @@ class RevDel_LogItem extends RevDel_Item { } public function getHTML() { - global $wgLang; - - $date = htmlspecialchars( $wgLang->timeanddate( $this->row->log_timestamp ) ); + $date = htmlspecialchars( $this->list->getLang()->timeanddate( $this->row->log_timestamp ) ); $paramArray = LogPage::extractParams( $this->row->log_params ); $title = Title::makeTitle( $this->row->log_namespace, $this->row->log_title ); // Log link for this page - $loglink = $this->special->skin->link( + $loglink = Linker::link( SpecialPage::getTitleFor( 'Log' ), wfMsgHtml( 'log' ), array(), @@ -669,19 +858,20 @@ class RevDel_LogItem extends RevDel_Item { if( !$this->canView() ) { $action = '' . wfMsgHtml('rev-deleted-event') . ''; } else { - $action = LogPage::actionText( $this->row->log_type, $this->row->log_action, $title, - $this->special->skin, $paramArray, true, true ); + $skin = $this->list->getUser()->getSkin(); + $action = LogPage::actionText( $this->row->log_type, $this->row->log_action, + $title, $skin, $paramArray, true, true ); if( $this->row->log_deleted & LogPage::DELETED_ACTION ) $action = '' . $action . ''; } // User links - $userLink = $this->special->skin->userLink( $this->row->log_user, + $userLink = Linker::userLink( $this->row->log_user, User::WhoIs( $this->row->log_user ) ); if( LogEventsList::isDeleted($this->row,LogPage::DELETED_USER) ) { $userLink = '' . $userLink . ''; } // Comment - $comment = $wgLang->getDirMark() . $this->special->skin->commentBlock( $this->row->log_comment ); + $comment = $this->list->getLang()->getDirMark() . Linker::commentBlock( $this->row->log_comment ); if( LogEventsList::isDeleted($this->row,LogPage::DELETED_COMMENT) ) { $comment = '' . $comment . ''; } diff --git a/includes/revisiondelete/RevisionDeleteAbstracts.php b/includes/revisiondelete/RevisionDeleteAbstracts.php index 073c25ba..73af1e5f 100644 --- a/includes/revisiondelete/RevisionDeleteAbstracts.php +++ b/includes/revisiondelete/RevisionDeleteAbstracts.php @@ -1,63 +1,28 @@ special = $special; - $this->title = $title; +abstract class RevDel_List extends Rev_List { + function __construct( IContextSource $context, Title $title, array $ids ) { + parent::__construct( $context, $title ); $this->ids = $ids; } /** - * Get the internal type name of this list. Equal to the table name. - */ - public function getType() { - return $this->type; - } - - /** - * Get the DB field name associated with the ID list - */ - public function getIdField() { - return $this->idField; - } - - /** - * Get the DB field name storing timestamps + * Get the DB field name associated with the ID list. + * This used to populate the log_search table for finding log entries. + * Override this function. */ - public function getTimestampField() { - return $this->dateField; + public static function getRelationType() { + return null; } /** - * 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 + * Set the visibility for the revisions in this list. Logging and * transactions are done here. * * @param $params Associative array of parameters. Members are: @@ -118,7 +83,7 @@ abstract class RevDel_List { $status->warning( 'revdelete-only-restricted', $item->formatDate(), $item->formatTime() ); $status->failCount++; continue; - } + } // Update the revision $ok = $item->setBits( $newBits ); @@ -128,7 +93,7 @@ abstract class RevDel_List { $status->successCount++; if( $item->getAuthorId() > 0 ) { $authorIds[] = $item->getAuthorId(); - } else if( IP::isIPAddress( $item->getAuthorName() ) ) { + } elseif( IP::isIPAddress( $item->getAuthorName() ) ) { $authorIPs[] = $item->getAuthorName(); } } else { @@ -149,7 +114,7 @@ abstract class RevDel_List { return $status; } - // Save success count + // Save success count $successCount = $status->successCount; // Move files, if there are any @@ -162,9 +127,9 @@ abstract class RevDel_List { // Log it $this->updateLog( array( - 'title' => $this->title, - 'count' => $successCount, - 'newBits' => $newBits, + 'title' => $this->title, + 'count' => $successCount, + 'newBits' => $newBits, 'oldBits' => $oldBits, 'comment' => $comment, 'ids' => $idsForLog, @@ -191,7 +156,7 @@ abstract class RevDel_List { * Record a log entry on the action * @param $params Associative array of parameters: * newBits: The new value of the *_deleted bitfield - * oldBits: The old value of the *_deleted bitfield. + * oldBits: The old value of the *_deleted bitfield. * title: The target title * ids: The ID list * comment: The log comment @@ -243,59 +208,6 @@ abstract class RevDel_List { ); } - /** - * Initialise the current iteration pointer - */ - protected function initCurrent() { - $row = $this->res->current(); - if ( $row ) { - $this->current = $this->newItem( $row ); - } else { - $this->current = false; - } - } - - /** - * Start iteration. This must be called before current() or next(). - * @return First list item - */ - public function reset() { - if ( !$this->res ) { - $this->res = $this->doQuery( wfGetDB( DB_SLAVE ) ); - } else { - $this->res->rewind(); - } - $this->initCurrent(); - return $this->current; - } - - /** - * Get the current list item, or false if we are at the end - */ - public function current() { - return $this->current; - } - - /** - * Move the iteration pointer to the next list item, and return it. - */ - public function next() { - $this->res->next(); - $this->initCurrent(); - return $this->current; - } - - /** - * Get the number of items in the list. - */ - public function length() { - if( !$this->res ) { - return 0; - } else { - return $this->res->numRows(); - } - } - /** * Clear any data structures needed for doPreCommitUpdates() and doPostCommitUpdates() * STUB @@ -303,7 +215,7 @@ abstract class RevDel_List { public function clearFileOps() { } - /** + /** * A hook for setVisibility(): do batch updates pre-commit. * STUB * @return Status @@ -313,26 +225,14 @@ abstract class RevDel_List { } /** - * A hook for setVisibility(): do any necessary updates post-commit. + * A hook for setVisibility(): do any necessary updates post-commit. * STUB - * @return Status + * @return Status */ public function doPostCommitUpdates() { return Status::newGood(); } - /** - * Create an item object from a DB result row - * @param $row stdclass - */ - abstract public function newItem( $row ); - - /** - * Do the DB query to iterate through the objects. - * @param $db Database object to use for the query - */ - abstract public function doQuery( $db ); - /** * Get the integer value of the flag used for suppression */ @@ -342,75 +242,8 @@ abstract class RevDel_List { /** * Abstract base class for deletable items */ -abstract class RevDel_Item { - /** The parent SpecialPage */ - var $special; - - /** The parent RevDel_List */ - var $list; - - /** The DB result row */ - var $row; - - /** - * @param $list RevDel_List - * @param $row DB result row - */ - public function __construct( $list, $row ) { - $this->special = $list->special; - $this->list = $list; - $this->row = $row; - } - +abstract class RevDel_Item extends Rev_Item { /** - * Get the ID, as it would appear in the ids URL parameter - */ - public function getId() { - $field = $this->list->getIdField(); - return $this->row->$field; - } - - /** - * Get the date, formatted with $wgLang - */ - public function formatDate() { - global $wgLang; - return $wgLang->date( $this->getTimestamp() ); - } - - /** - * Get the time, formatted with $wgLang - */ - public function formatTime() { - global $wgLang; - return $wgLang->time( $this->getTimestamp() ); - } - - /** - * Get the timestamp in MW 14-char form - */ - public function getTimestamp() { - $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 * bits can't be executed for that reason * STUB @@ -419,33 +252,17 @@ abstract class RevDel_Item { return false; } - /** - * Returns true if the current user can view the item - */ - abstract public function canView(); - - /** - * Returns true if the current user can view the item text/file - */ - abstract public function canViewContent(); - /** * Get the current deletion bitfield value */ abstract public function getBits(); - /** - * Get the HTML of the list item. Should be include
  • tags. - * This is used to show the list in HTML form, by the special page. - */ - abstract public function getHTML(); - /** * Set the visibility of the item. This should do any necessary DB queries. * * The DB update query should have a condition which forces it to only update - * if the value in the DB matches the value fetched earlier with the SELECT. - * If the update fails because it did not match, the function should return + * if the value in the DB matches the value fetched earlier with the SELECT. + * If the update fails because it did not match, the function should return * false. This prevents concurrency problems. * * @return boolean success diff --git a/includes/revisiondelete/RevisionDeleteUser.php b/includes/revisiondelete/RevisionDeleteUser.php new file mode 100644 index 00000000..c88b4d91 --- /dev/null +++ b/includes/revisiondelete/RevisionDeleteUser.php @@ -0,0 +1,130 @@ +getDBkey(); + + # Hide name from live edits + $dbw->update( + 'revision', + array( "rev_deleted = rev_deleted $op $delUser" ), + array( 'rev_user' => $userId ), + __METHOD__ ); + + # Hide name from deleted edits + $dbw->update( + 'archive', + array( "ar_deleted = ar_deleted $op $delUser" ), + array( 'ar_user_text' => $name ), + __METHOD__ + ); + + # Hide name from logs + $dbw->update( + 'logging', + array( "log_deleted = log_deleted $op $delUser" ), + array( 'log_user' => $userId, "log_type != 'suppress'" ), + __METHOD__ + ); + $dbw->update( + 'logging', + array( "log_deleted = log_deleted $op $delAction" ), + array( 'log_namespace' => NS_USER, 'log_title' => $userDbKey, + "log_type != 'suppress'" ), + __METHOD__ + ); + + # Hide name from RC + $dbw->update( + 'recentchanges', + array( "rc_deleted = rc_deleted $op $delUser" ), + array( 'rc_user_text' => $name ), + __METHOD__ + ); + $dbw->update( + 'recentchanges', + array( "rc_deleted = rc_deleted $op $delAction" ), + array( 'rc_namespace' => NS_USER, 'rc_title' => $userDbKey, 'rc_logid > 0' ), + __METHOD__ + ); + + # Hide name from live images + $dbw->update( + 'oldimage', + array( "oi_deleted = oi_deleted $op $delUser" ), + array( 'oi_user_text' => $name ), + __METHOD__ + ); + + # Hide name from deleted images + $dbw->update( + 'filearchive', + array( "fa_deleted = fa_deleted $op $delUser" ), + array( 'fa_user_text' => $name ), + __METHOD__ + ); + # Done! + return true; + } + + public static function suppressUserName( $name, $userId, $dbw = null ) { + return self::setUsernameBitfields( $name, $userId, '|', $dbw ); + } + + public static function unsuppressUserName( $name, $userId, $dbw = null ) { + return self::setUsernameBitfields( $name, $userId, '&', $dbw ); + } +} \ No newline at end of file diff --git a/includes/revisiondelete/RevisionDeleter.php b/includes/revisiondelete/RevisionDeleter.php index d47fcecf..bde586c5 100644 --- a/includes/revisiondelete/RevisionDeleter.php +++ b/includes/revisiondelete/RevisionDeleter.php @@ -18,7 +18,7 @@ class RevisionDeleter { * enabled / disabled. * @param $field Integer: the bitmask describing the single option. * @param $diff Integer: the xor of the old and new bitfields. - * @param $new Integer: the new bitfield + * @param $new Integer: the new bitfield * @param $arr Array: the array to update. */ protected static function checkItem( $desc, $field, $diff, $new, &$arr ) { @@ -29,10 +29,10 @@ class RevisionDeleter { /** * Gets an array of message keys describing the changes made to the visibility - * of the revision. If the resulting array is $arr, then $arr[0] will contain an - * array of strings describing the items that were hidden, $arr[2] will contain - * an array of strings describing the items that were unhidden, and $arr[3] will - * contain an array with a single string, which can be one of "applied + * of the revision. If the resulting array is $arr, then $arr[0] will contain an + * array of strings describing the items that were hidden, $arr[2] will contain + * an array of strings describing the items that were unhidden, and $arr[3] will + * contain an array with a single string, which can be one of "applied * restrictions to sysops", "removed restrictions from sysops", or null. * * @param $n Integer: the new bitfield. @@ -67,48 +67,39 @@ class RevisionDeleter { * @param $count Integer: The number of effected revisions. * @param $nbitfield Integer: The new bitfield for the revision. * @param $obitfield Integer: The old bitfield for the revision. + * @param $language Language object to use * @param $isForLog Boolean - * @param $forContent Boolean */ - public static function getLogMessage( $count, $nbitfield, $obitfield, $isForLog = false, $forContent = false ) { - global $wgLang, $wgContLang; - - $lang = $forContent ? $wgContLang : $wgLang; - $msgFunc = $forContent ? "wfMsgForContent" : "wfMsg"; - + public static function getLogMessage( $count, $nbitfield, $obitfield, $language, $isForLog = false ) { $changes = self::getChanges( $nbitfield, $obitfield ); - array_walk($changes, 'RevisionDeleter::expandMessageArray', $forContent); - + array_walk( $changes, array( __CLASS__, 'expandMessageArray' ), $language ); + $changesText = array(); - + if( count( $changes[0] ) ) { - $changesText[] = $msgFunc( 'revdelete-hid', $lang->commaList( $changes[0] ) ); + $changesText[] = wfMsgExt( 'revdelete-hid', array( 'parsemag', 'language' => $language ), $language->commaList( $changes[0] ) ); } if( count( $changes[1] ) ) { - $changesText[] = $msgFunc( 'revdelete-unhid', $lang->commaList( $changes[1] ) ); + $changesText[] = wfMsgExt( 'revdelete-unhid', array( 'parsemag', 'language' => $language ), $language->commaList( $changes[1] ) ); } - - $s = $lang->semicolonList( $changesText ); + + $s = $language->semicolonList( $changesText ); if( count( $changes[2] ) ) { $s .= $s ? ' (' . $changes[2][0] . ')' : ' ' . $changes[2][0]; } - + $msg = $isForLog ? 'logdelete-log-message' : 'revdelete-log-message'; - return wfMsgExt( $msg, $forContent ? array( 'parsemag', 'content' ) : array( 'parsemag' ), $s, $lang->formatNum($count) ); + return wfMsgExt( $msg, array( 'parsemag', 'language' => $language ), $s, $language->formatNum($count) ); } - - private static function expandMessageArray(& $msg, $key, $forContent) { - if ( is_array ($msg) ) { - array_walk($msg, 'RevisionDeleter::expandMessageArray', $forContent); + + private static function expandMessageArray( &$msg, $key, $language ) { + if ( is_array ( $msg ) ) { + array_walk( $msg, array( __CLASS__, 'expandMessageArray' ), $language ); } else { - if ( $forContent ) { - $msg = wfMsgForContent($msg); - } else { - $msg = wfMsg($msg); - } + $msg = wfMsgExt( $msg, array( 'parsemag', 'language' => $language ) ); } } - + // Get DB field name for URL param... // Future code for other things may also track // other types of revision-specific changes. @@ -119,75 +110,62 @@ class RevisionDeleter { } if ( isset( SpecialRevisionDelete::$allowedTypes[$typeName] ) ) { $class = SpecialRevisionDelete::$allowedTypes[$typeName]['list-class']; - $list = new $class( null, null, null ); - return $list->getIdField(); + return call_user_func( array( $class, 'getRelationType' ) ); } else { return null; } } - - // Checks if a revision still exists in the revision table. - // If it doesn't, returns the corresponding ar_timestamp field - // so that this key can be used instead. + + /** + * Checks if a revision still exists in the revision table. + * If it doesn't, returns the corresponding ar_timestamp field + * so that this key can be used instead. + * + * @param $title Title + * @param $revid + * @return bool|mixed + */ public static function checkRevisionExistence( $title, $revid ) { $dbr = wfGetDB( DB_SLAVE ); $exists = $dbr->selectField( 'revision', '1', array( 'rev_id' => $revid ), __METHOD__ ); - + if ( $exists ) { return true; } - + $timestamp = $dbr->selectField( 'archive', 'ar_timestamp', array( 'ar_namespace' => $title->getNamespace(), 'ar_title' => $title->getDBkey(), 'ar_rev_id' => $revid ), __METHOD__ ); - + return $timestamp; } - - // Creates utility links for log entries. + + /** + * Creates utility links for log entries. + * + * @param $title Title + * @param $paramArray Array + * @param $skin Skin + * @param $messages + * @return String + */ public static function getLogLinks( $title, $paramArray, $skin, $messages ) { global $wgLang; - - if( count($paramArray) >= 2 ) { + + if ( count( $paramArray ) >= 2 ) { // Different revision types use different URL params... $originalKey = $key = $paramArray[0]; // $paramArray[1] is a CSV of the IDs $Ids = explode( ',', $paramArray[1] ); $revert = array(); - - // For if undeleted revisions are found amidst deleted ones. - $undeletedRevisions = array(); - - // This is not going to work if some revs are deleted and some - // aren't. - if ($key == 'revision') { - foreach( $Ids as $k => $id ) { - $existResult = - self::checkRevisionExistence( $title, $id ); - - if ($existResult !== true) { - $key = 'archive'; - $Ids[$k] = $existResult; - } else { - // Undeleted revision amidst deleted ones - unset($Ids[$k]); - $undeletedRevisions[] = $id; - } - } - - if ( $key == $originalKey ) { - $Ids = $undeletedRevisions; - $undeletedRevisions = array(); - } - } - + // Diff link for single rev deletions - if( count($Ids) == 1 && !count($undeletedRevisions) ) { + if ( count( $Ids ) == 1 ) { // Live revision diffs... - if( in_array( $key, array( 'oldid', 'revision' ) ) ) { + if ( in_array( $key, array( 'oldid', 'revision' ) ) ) { $revert[] = $skin->link( $title, $messages['diff'], @@ -199,10 +177,10 @@ class RevisionDeleter { array( 'known', 'noclasses' ) ); // Deleted revision diffs... - } else if( in_array( $key, array( 'artimestamp','archive' ) ) ) { + } elseif ( in_array( $key, array( 'artimestamp','archive' ) ) ) { $revert[] = $skin->link( SpecialPage::getTitleFor( 'Undelete' ), - $messages['diff'], + $messages['diff'], array(), array( 'target' => $title->getPrefixedDBKey(), @@ -213,58 +191,23 @@ class RevisionDeleter { ); } } - + // View/modify link... - if ( count($undeletedRevisions) ) { - // FIXME THIS IS A HORRIBLE HORRIBLE HACK AND SHOULD DIE - // It's not possible to pass a list of both deleted and - // undeleted revisions to SpecialRevisionDelete, so we're - // stuck with two links. See bug 23363. - $restoreLinks = array(); - - $restoreLinks[] = $skin->link( - SpecialPage::getTitleFor( 'Revisiondelete' ), - $messages['revdel-restore-visible'], - array(), - array( - 'target' => $title->getPrefixedText(), - 'type' => $originalKey, - 'ids' => implode(',', $undeletedRevisions), - ), - array( 'known', 'noclasses' ) - ); - - $restoreLinks[] = $skin->link( - SpecialPage::getTitleFor( 'Revisiondelete' ), - $messages['revdel-restore-deleted'], - array(), - array( - 'target' => $title->getPrefixedText(), - 'type' => $key, - 'ids' => implode(',', $Ids), - ), - array( 'known', 'noclasses' ) - ); - - $revert[] = $messages['revdel-restore'] . ' [' . - $wgLang->pipeList( $restoreLinks ) . ']'; - } else { - $revert[] = $skin->link( - SpecialPage::getTitleFor( 'Revisiondelete' ), - $messages['revdel-restore'], - array(), - array( - 'target' => $title->getPrefixedText(), - 'type' => $key, - 'ids' => implode(',', $Ids), - ), - array( 'known', 'noclasses' ) - ); - } - + $revert[] = $skin->link( + SpecialPage::getTitleFor( 'Revisiondelete' ), + $messages['revdel-restore'], + array(), + array( + 'target' => $title->getPrefixedText(), + 'type' => $key, + 'ids' => implode(',', $Ids), + ), + array( 'known', 'noclasses' ) + ); + // Pipe links return wfMsg( 'parentheses', $wgLang->pipeList( $revert ) ); } return ''; } -} \ No newline at end of file +} -- cgit v1.2.2