* (bug 21279) Special:RevisionDelete now uses revision ID for deleted-page revisions...
authorBrion Vibber <brion@users.mediawiki.org>
Tue, 10 May 2011 01:11:52 +0000 (01:11 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Tue, 10 May 2011 01:11:52 +0000 (01:11 +0000)
- saved Special:RevisionDelete links from before page deletion still work as-is after deletion
- old log entries for rev-delete adjustments no longer magically switch to linking to Special:RevisionDelete with archive & ar_timestamp (they remain the same, as the links continue to work)

If you call Special:RevisionDelete using the older-style &type=archive links (using ar_timestamp as id) it will still save the same form to log for now; this may be fixed later for cases where the ar_rev_id is available.

Requires FakeResultWrapper fixes from r87803.

includes/revisiondelete/RevisionDelete.php
includes/revisiondelete/RevisionDeleteAbstracts.php
includes/revisiondelete/RevisionDeleter.php

index c331ec6..5831996 100644 (file)
@@ -1,6 +1,12 @@
 <?php
 /**
  * List for revision table items
+ *
+ * This will check both the 'revision' table for live revisions and the
+ * 'archive' table for traditionally-deleted revisions that have an
+ * ar_rev_id saved.
+ *
+ * See RevDel_RevisionItem and RevDel_ArchivedRevisionItem for items.
  */
 class RevDel_RevisionList extends RevDel_List {
        var $currentRevId;
@@ -16,7 +22,7 @@ class RevDel_RevisionList extends RevDel_List {
         */
        public function doQuery( $db ) {
                $ids = array_map( 'intval', $this->ids );
-               return $db->select( array('revision','page'), '*',
+               $live = $db->select( array('revision','page'), '*',
                        array(
                                'rev_page' => $this->title->getArticleID(),
                                'rev_id'   => $ids,
@@ -25,10 +31,49 @@ 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;
+               } else if ( $live->numRows() == 0 ) {
+                       return $archived;
+               } else {
+                       // Combine the two! Whee
+                       $rows = array();
+                       while ( $row = $live->fetchObject() ) {
+                               $rows[$row->rev_id] = $row;
+                       }
+                       while ( $row = $archived->fetchObject() ) {
+                               $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. :)
+                       var_dump( $row );
+                       throw new MWException( 'Invalid row type in RevDel_RevisionList' );
+               }
        }
 
        public function getCurrent() {
@@ -58,7 +103,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;
@@ -281,6 +326,35 @@ 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 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
  */
index d57b879..1240f6e 100644 (file)
@@ -1,7 +1,10 @@
 <?php
 
 /**
- * Abstract base class for a list of deletable items
+ * Abstract base class for a list of deletable items. The list class
+ * needs to be able to make a query from a set of identifiers to pull
+ * relevant rows, to return RevDel_Item subclasses wrapping them, and
+ * to wrap bulk update operations.
  */
 abstract class RevDel_List {
 
index 623c08f..ea283ae 100644 (file)
@@ -178,24 +178,7 @@ class RevisionDeleter {
                        // 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();
-                               }
+                               // Nothing to do; deleted revisions can still be looked up by ID.
                        }
                        
                        // Diff link for single rev deletions