Anomie has uploaded a new change for review.
https://gerrit.wikimedia.org/r/70748
Change subject: Separate RevDel logic from UI
......................................................................
Separate RevDel logic from UI
Move functions implementing the actual revision deletion out of
SpecialRevisiondelete, so they can be used from elsewhere (e.g.
ApiRevisiondelete).
Change-Id: Id0f6b1c8dab474bdfd802c07b211885d398c94e5
---
M includes/revisiondelete/RevisionDelete.php
M includes/revisiondelete/RevisionDeleteAbstracts.php
M includes/revisiondelete/RevisionDeleter.php
M includes/specials/SpecialRevisiondelete.php
4 files changed, 227 insertions(+), 80 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/48/70748/1
diff --git a/includes/revisiondelete/RevisionDelete.php
b/includes/revisiondelete/RevisionDelete.php
index ac72276..68e4e60 100644
--- a/includes/revisiondelete/RevisionDelete.php
+++ b/includes/revisiondelete/RevisionDelete.php
@@ -41,6 +41,19 @@
return 'rev_id';
}
+ public static function getRestriction() {
+ return 'deleterevision';
+ }
+
+ public static function getRevdelConstant() {
+ return Revision::DELETED_TEXT;
+ }
+
+ public static function suggestTarget( $target, array $ids ) {
+ $rev = Revision::newFromId( $ids[0] );
+ return $rev ? $rev->getTitle() : $target;
+ }
+
/**
* @param $db DatabaseBase
* @return mixed
@@ -441,6 +454,14 @@
return 'oi_archive_name';
}
+ public static function getRestriction() {
+ return 'deleterevision';
+ }
+
+ public static function getRevdelConstant() {
+ return File::DELETED_FILE;
+ }
+
var $storeBatch, $deleteBatch, $cleanupBatch;
/**
@@ -791,6 +812,28 @@
return 'log_id';
}
+ public static function getRestriction() {
+ return 'deletelogentry';
+ }
+
+ public static function getRevdelConstant() {
+ return LogPage::DELETED_ACTION;
+ }
+
+ public static function suggestTarget( $target, array $ids ) {
+ $result = wfGetDB( DB_SLAVE )->select( 'logging',
+ 'log_type',
+ array( 'log_id' => $ids ),
+ __METHOD__,
+ array( 'DISTINCT' )
+ );
+ if ( $result->numRows() == 1 ) {
+ // If there's only one type, the target can be set to
include it.
+ return SpecialPage::getTitleFor( 'Log',
$result->current()->log_type );
+ }
+ return SpecialPage::getTitleFor( 'Log' );
+ }
+
/**
* @param $db DatabaseBase
* @return mixed
diff --git a/includes/revisiondelete/RevisionDeleteAbstracts.php
b/includes/revisiondelete/RevisionDeleteAbstracts.php
index 9ace35a..59118bc 100644
--- a/includes/revisiondelete/RevisionDeleteAbstracts.php
+++ b/includes/revisiondelete/RevisionDeleteAbstracts.php
@@ -44,6 +44,38 @@
}
/**
+ * Get the user right required for this list type
+ * Override this function.
+ * @since 1.22
+ * @return null
+ */
+ public static function getRestriction() {
+ return null;
+ }
+
+ /**
+ * Get the revision deletion constant for this list type
+ * Override this function.
+ * @since 1.22
+ * @return null
+ */
+ public static function getRevdelConstant() {
+ return null;
+ }
+
+ /**
+ * Suggest a target for the revision deletion
+ * Optionally override this function.
+ * @since 1.22
+ * @params Title $target User-supplied target
+ * @params array $ids
+ * @return null
+ */
+ public static function suggestTarget( $target, array $ids ) {
+ return $target;
+ }
+
+ /**
* Set the visibility for the revisions in this list. Logging and
* transactions are done here.
*
@@ -72,7 +104,7 @@
$oldBits = $item->getBits();
// Build the actual new rev_deleted bitfield
- $newBits = SpecialRevisionDelete::extractBitfield(
$bitPars, $oldBits );
+ $newBits = RevisionDeleter::extractBitfield( $bitPars,
$oldBits );
if ( $oldBits == $newBits ) {
$status->warning( 'revdelete-no-change',
$item->formatDate(), $item->formatTime() );
diff --git a/includes/revisiondelete/RevisionDeleter.php
b/includes/revisiondelete/RevisionDeleter.php
index 2de19ac..48e4b9f 100644
--- a/includes/revisiondelete/RevisionDeleter.php
+++ b/includes/revisiondelete/RevisionDeleter.php
@@ -22,11 +22,71 @@
*/
/**
- * Temporary b/c interface, collection of static functions.
- * @ingroup SpecialPage
+ * General controller for RevDel, used by both SpecialRevisiondelete and
+ * ApiRevisiondelete.
* @ingroup RevisionDelete
*/
class RevisionDeleter {
+ /** List of known revdel types, with their corresponding list classes */
+ private static $allowedTypes = array(
+ 'revision' => 'RevDel_RevisionList',
+ 'archive' => 'RevDel_ArchiveList',
+ 'oldimage' => 'RevDel_FileList',
+ 'filearchive' => 'RevDel_ArchivedFileList',
+ 'logging' => 'RevDel_LogList',
+ );
+
+ /** Type map to support old log entries */
+ private static $deprecatedTypeMap = array(
+ 'oldid' => 'revision',
+ 'artimestamp' => 'archive',
+ 'oldimage' => 'oldimage',
+ 'fileid' => 'filearchive',
+ 'logid' => 'logging',
+ );
+
+ /**
+ * Lists the valid possible types for revision deletion.
+ *
+ * @since 1.22
+ * @return array
+ */
+ public static function getTypes() {
+ return array_keys( self::$allowedTypes );
+ }
+
+ /**
+ * Gets the canonical type name, if any.
+ *
+ * @since 1.22
+ * @param string $typeName
+ * @return string|null
+ */
+ public static function getCanonicalTypeName( $typeName ) {
+ if ( isset( self::$deprecatedTypeMap[$typeName] ) ) {
+ $typeName = self::$deprecatedTypeMap[$typeName];
+ }
+ return isset( self::$allowedTypes[$typeName] ) ? $typeName :
null;
+ }
+
+ /**
+ * Instantiate the appropriate list class for a given list of IDs.
+ *
+ * @since 1.22
+ * @param string $typeName RevDel type, see RevisionDeleter::getTypes()
+ * @param IContextSource $context
+ * @param Title $title
+ * @param array $ids
+ * @return RevDel_List
+ */
+ public static function createList( $typeName, IContextSource $context,
Title $title, array $ids ) {
+ $typeName = self::getCanonicalTypeName( $typeName );
+ if ( !$typeName ) {
+ throw new MWException( __METHOD__ . ": Unknown RevDel
type '$typeName'" );
+ }
+ return new self::$allowedTypes[$typeName]( $context, $title,
$ids );
+ }
+
/**
* Checks for a change in the bitfield for a certain option and updates
the
* provided array accordingly.
@@ -86,19 +146,61 @@
/** Get DB field name for URL param...
* Future code for other things may also track
* other types of revision-specific changes.
+ * @param string $typeName
* @return 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];
- }
- if ( isset( SpecialRevisionDelete::$allowedTypes[$typeName] ) )
{
- $class =
SpecialRevisionDelete::$allowedTypes[$typeName]['list-class'];
- return call_user_func( array( $class, 'getRelationType'
) );
- } else {
+ $typeName = self::getCanonicalTypeName( $typeName );
+ if ( !$typeName ) {
return null;
}
+ return call_user_func( array( self::$allowedTypes[$typeName],
'getRelationType' ) );
}
+
+ /**
+ * Get the user right required for the RevDel type
+ * @since 1.22
+ * @param string $typeName
+ * @return string User right
+ */
+ public static function getRestriction( $typeName ) {
+ $typeName = self::getCanonicalTypeName( $typeName );
+ if ( !$typeName ) {
+ return null;
+ }
+ return call_user_func( array( self::$allowedTypes[$typeName],
'getRestriction' ) );
+ }
+
+ /**
+ * Get the revision deletion constant for the RevDel type
+ * @since 1.22
+ * @param string $typeName
+ * @return int RevDel constant
+ */
+ public static function getRevdelConstant( $typeName ) {
+ $typeName = self::getCanonicalTypeName( $typeName );
+ if ( !$typeName ) {
+ return null;
+ }
+ return call_user_func( array( self::$allowedTypes[$typeName],
'getRevdelConstant' ) );
+ }
+
+ /**
+ * Suggest a target for the revision deletion
+ * @since 1.22
+ * @param string $typeName
+ * @param Title $title User-supplied target
+ * @param array $ids
+ * @return Title|null
+ */
+ public static function suggestTarget( $typeName, $target, array $ids ) {
+ $typeName = self::getCanonicalTypeName( $typeName );
+ if ( !$typeName ) {
+ return $target;
+ }
+ return call_user_func( array( self::$allowedTypes[$typeName],
'suggestTarget' ), $target, $ids );
+ }
+
/**
* Checks if a revision still exists in the revision table.
@@ -125,4 +227,24 @@
return $timestamp;
}
+
+ /**
+ * Put together a rev_deleted bitfield
+ * @since 1.22
+ * @param array $bitPars extractBitParams() params
+ * @param int $oldfield current bitfield
+ * @return array
+ */
+ public static function extractBitfield( $bitPars, $oldfield ) {
+ // Build the actual new rev_deleted bitfield
+ $newBits = 0;
+ foreach ( $bitPars as $const => $val ) {
+ if ( $val == 1 ) {
+ $newBits |= $const; // $const is the *_deleted
const
+ } elseif ( $val == -1 ) {
+ $newBits |= ( $oldfield & $const ); // use
existing
+ }
+ }
+ return $newBits;
+ }
}
diff --git a/includes/specials/SpecialRevisiondelete.php
b/includes/specials/SpecialRevisiondelete.php
index 9f4b9da..30f0dd9 100644
--- a/includes/specials/SpecialRevisiondelete.php
+++ b/includes/specials/SpecialRevisiondelete.php
@@ -49,66 +49,41 @@
/** Array of checkbox specs (message, name, deletion bits) */
var $checks;
- /** Information about the current type */
- var $typeInfo;
+ /** UI Labels about the current type */
+ var $typeLabels;
/** The RevDel_List object, storing the list of items to be
deleted/undeleted */
var $list;
/**
- * Assorted information about each type, needed by the special page.
- * TODO Move some of this to the list class
+ * UI labels for each type.
*/
- static $allowedTypes = array(
+ static $UILabels = array(
'revision' => array(
'check-label' => 'revdelete-hide-text',
- 'deletion-bits' => Revision::DELETED_TEXT,
'success' => 'revdelete-success',
'failure' => 'revdelete-failure',
- 'list-class' => 'RevDel_RevisionList',
- 'permission' => 'deleterevision',
),
'archive' => array(
'check-label' => 'revdelete-hide-text',
- 'deletion-bits' => Revision::DELETED_TEXT,
'success' => 'revdelete-success',
'failure' => 'revdelete-failure',
- 'list-class' => 'RevDel_ArchiveList',
- 'permission' => 'deleterevision',
),
'oldimage' => array(
'check-label' => 'revdelete-hide-image',
- 'deletion-bits' => File::DELETED_FILE,
'success' => 'revdelete-success',
'failure' => 'revdelete-failure',
- 'list-class' => 'RevDel_FileList',
- 'permission' => 'deleterevision',
),
'filearchive' => array(
'check-label' => 'revdelete-hide-image',
- 'deletion-bits' => File::DELETED_FILE,
'success' => 'revdelete-success',
'failure' => 'revdelete-failure',
- 'list-class' => 'RevDel_ArchivedFileList',
- 'permission' => 'deleterevision',
),
'logging' => array(
'check-label' => 'revdelete-hide-name',
- 'deletion-bits' => LogPage::DELETED_ACTION,
'success' => 'logdelete-success',
'failure' => 'logdelete-failure',
- 'list-class' => 'RevDel_LogList',
- 'permission' => 'deletelogentry',
),
- );
-
- /** Type map to support old log entries */
- static $deprecatedTypeMap = array(
- 'oldid' => 'revision',
- 'artimestamp' => 'archive',
- 'oldimage' => 'oldimage',
- 'fileid' => 'filearchive',
- 'logid' => 'logging',
);
public function __construct() {
@@ -147,19 +122,6 @@
} else {
$this->typeName = $request->getVal( 'type' );
$this->targetObj = Title::newFromText(
$request->getText( 'target' ) );
- if ( $this->targetObj && $this->targetObj->isSpecial(
'Log' ) && count( $this->ids ) !== 0 ) {
- $result = wfGetDB( DB_SLAVE )->select(
'logging',
- 'log_type',
- array( 'log_id' => $this->ids ),
- __METHOD__,
- array( 'DISTINCT' )
- );
-
- if ( $result->numRows() == 1 ) {
- // If there's only one type, the target
can be set to include it.
- $this->targetObj =
SpecialPage::getTitleFor( 'Log', $result->current()->log_type );
- }
- }
}
# For reviewing deleted files...
@@ -170,24 +132,17 @@
return;
}
- if ( isset( self::$deprecatedTypeMap[$this->typeName] ) ) {
- $this->typeName =
self::$deprecatedTypeMap[$this->typeName];
- }
+ $this->typeName = RevisionDeleter::getCanonicalTypeName(
$this->typeName );
# No targets?
- if ( !isset( self::$allowedTypes[$this->typeName] ) || count(
$this->ids ) == 0 ) {
+ if ( !$this->typeName || count( $this->ids ) == 0 ) {
throw new ErrorPageError( 'revdelete-nooldid-title',
'revdelete-nooldid-text' );
}
- $this->typeInfo = self::$allowedTypes[$this->typeName];
- $this->mIsAllowed = $user->isAllowed(
$this->typeInfo['permission'] );
+ $this->typeLabels = self::$UILabels[$this->typeName];
+ $this->mIsAllowed = $user->isAllowed(
RevisionDeleter::getRestriction( $this->typeName ) );
- # If we have revisions, get the title from the first one
- # since they should all be from the same page. This allows
- # for more flexibility with page moves...
- if ( $this->typeName == 'revision' ) {
- $rev = Revision::newFromId( $this->ids[0] );
- $this->targetObj = $rev ? $rev->getTitle() :
$this->targetObj;
- }
+ # Allow the list type to adjust the passed target
+ $this->targetObj = RevisionDeleter::suggestTarget(
$this->typeName, $this->targetObj, $this->ids );
$this->otherReason = $request->getVal( 'wpReason' );
# We need a target page!
@@ -200,7 +155,9 @@
# Initialise checkboxes
$this->checks = array(
- array( $this->typeInfo['check-label'], 'wpHidePrimary',
$this->typeInfo['deletion-bits'] ),
+ array( $this->typeLabels['check-label'],
'wpHidePrimary',
+ RevisionDeleter::getRevdelConstant(
$this->typeName )
+ ),
array( 'revdelete-hide-comment', 'wpHideComment',
Revision::DELETED_COMMENT ),
array( 'revdelete-hide-user', 'wpHideUser',
Revision::DELETED_USER )
);
@@ -343,8 +300,9 @@
*/
protected function getList() {
if ( is_null( $this->list ) ) {
- $class = $this->typeInfo['list-class'];
- $this->list = new $class( $this->getContext(),
$this->targetObj, $this->ids );
+ $this->list = RevisionDeleter::createList(
+ $this->typeName, $this->getContext(),
$this->targetObj, $this->ids
+ );
}
return $this->list;
}
@@ -561,7 +519,7 @@
*/
protected function success() {
$this->getOutput()->setPageTitle( $this->msg( 'actioncomplete'
) );
- $this->getOutput()->wrapWikiMsg( "<span
class=\"success\">\n$1\n</span>", $this->typeInfo['success'] );
+ $this->getOutput()->wrapWikiMsg( "<span
class=\"success\">\n$1\n</span>", $this->typeLabels['success'] );
$this->list->reloadFromMaster();
$this->showForm();
}
@@ -571,7 +529,7 @@
*/
protected function failure( $status ) {
$this->getOutput()->setPageTitle( $this->msg( 'actionfailed' )
);
- $this->getOutput()->addWikiText( $status->getWikiText(
$this->typeInfo['failure'] ) );
+ $this->getOutput()->addWikiText( $status->getWikiText(
$this->typeLabels['failure'] ) );
$this->showForm();
}
@@ -598,21 +556,13 @@
/**
* Put together a rev_deleted bitfield
+ * @deprecated since 1.22, use RevisionDeleter::extractBitfield instead
* @param array $bitPars extractBitParams() params
* @param int $oldfield current bitfield
* @return array
*/
public static function extractBitfield( $bitPars, $oldfield ) {
- // Build the actual new rev_deleted bitfield
- $newBits = 0;
- foreach ( $bitPars as $const => $val ) {
- if ( $val == 1 ) {
- $newBits |= $const; // $const is the *_deleted
const
- } elseif ( $val == -1 ) {
- $newBits |= ( $oldfield & $const ); // use
existing
- }
- }
- return $newBits;
+ return RevisionDeleter::extractBitfield( $bitPars, $oldfield );
}
/**
--
To view, visit https://gerrit.wikimedia.org/r/70748
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id0f6b1c8dab474bdfd802c07b211885d398c94e5
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits