Merge "Add tags support to patrol, protect, unblock, and undelete"

This commit is contained in:
jenkins-bot 2016-03-03 16:28:45 +00:00 committed by Gerrit Code Review
commit 996b7350f3
14 changed files with 141 additions and 23 deletions

View file

@ -56,7 +56,18 @@ class ApiPatrol extends ApiBase {
}
}
$retval = $rc->doMarkPatrolled( $this->getUser() );
$user = $this->getUser();
$tags = $params['tags'];
// Check if user can add tags
if ( !is_null( $tags ) ) {
$ableToTag = ChangeTags::canAddTagsAccompanyingChange( $tags, $user );
if ( !$ableToTag->isOK() ) {
$this->dieStatus( $ableToTag );
}
}
$retval = $rc->doMarkPatrolled( $user, false, $tags );
if ( $retval ) {
$this->dieUsageMsg( reset( $retval ) );
@ -83,6 +94,10 @@ class ApiPatrol extends ApiBase {
'revid' => [
ApiBase::PARAM_TYPE => 'integer'
],
'tags' => [
ApiBase::PARAM_TYPE => 'tags',
ApiBase::PARAM_ISMULTI => true,
],
];
}

View file

@ -42,6 +42,17 @@ class ApiProtect extends ApiBase {
$this->dieUsageMsg( reset( $errors ) );
}
$user = $this->getUser();
$tags = $params['tags'];
// Check if user can add tags
if ( !is_null( $tags ) ) {
$ableToTag = ChangeTags::canAddTagsAccompanyingChange( $tags, $user );
if ( !$ableToTag->isOK() ) {
$this->dieStatus( $ableToTag );
}
}
$expiry = (array)$params['expiry'];
if ( count( $expiry ) != count( $params['protections'] ) ) {
if ( count( $expiry ) == 1 ) {
@ -108,7 +119,8 @@ class ApiProtect extends ApiBase {
$expiryarray,
$cascade,
$params['reason'],
$this->getUser()
$user,
$tags
);
if ( !$status->isOK() ) {
@ -153,6 +165,10 @@ class ApiProtect extends ApiBase {
ApiBase::PARAM_DFLT => 'infinite',
],
'reason' => '',
'tags' => [
ApiBase::PARAM_TYPE => 'tags',
ApiBase::PARAM_ISMULTI => true,
],
'cascade' => false,
'watch' => [
ApiBase::PARAM_DFLT => false,

View file

@ -63,9 +63,18 @@ class ApiUnblock extends ApiBase {
}
}
// Check if user can add tags
if ( !is_null( $params['tags'] ) ) {
$ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
if ( !$ableToTag->isOK() ) {
$this->dieStatus( $ableToTag );
}
}
$data = [
'Target' => is_null( $params['id'] ) ? $params['user'] : "#{$params['id']}",
'Reason' => $params['reason']
'Reason' => $params['reason'],
'Tags' => $params['tags']
];
$block = Block::newFromTarget( $data['Target'] );
$retval = SpecialUnblock::processUnblock( $data, $this->getContext() );
@ -96,6 +105,10 @@ class ApiUnblock extends ApiBase {
],
'user' => null,
'reason' => '',
'tags' => [
ApiBase::PARAM_TYPE => 'tags',
ApiBase::PARAM_ISMULTI => true,
],
];
}

View file

@ -47,6 +47,14 @@ class ApiUndelete extends ApiBase {
$this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
}
// Check if user can add tags
if ( !is_null( $params['tags'] ) ) {
$ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
if ( !$ableToTag->isOK() ) {
$this->dieStatus( $ableToTag );
}
}
// Convert timestamps
if ( !isset( $params['timestamps'] ) ) {
$params['timestamps'] = [];
@ -64,7 +72,8 @@ class ApiUndelete extends ApiBase {
$params['reason'],
$params['fileids'],
false,
$this->getUser()
$user,
$params['tags']
);
if ( !is_array( $retval ) ) {
$this->dieUsageMsg( 'cannotundelete' );
@ -99,6 +108,10 @@ class ApiUndelete extends ApiBase {
ApiBase::PARAM_REQUIRED => true
],
'reason' => '',
'tags' => [
ApiBase::PARAM_TYPE => 'tags',
ApiBase::PARAM_ISMULTI => true,
],
'timestamps' => [
ApiBase::PARAM_TYPE => 'timestamp',
ApiBase::PARAM_ISMULTI => true,

View file

@ -343,6 +343,7 @@
"apihelp-patrol-description": "Patrol a page or revision.",
"apihelp-patrol-param-rcid": "Recentchanges ID to patrol.",
"apihelp-patrol-param-revid": "Revision ID to patrol.",
"apihelp-patrol-param-tags": "Change tags to apply to the entry in the patrol log.",
"apihelp-patrol-example-rcid": "Patrol a recent change.",
"apihelp-patrol-example-revid": "Patrol a revision.",
@ -352,6 +353,7 @@
"apihelp-protect-param-protections": "List of protection levels, formatted <kbd>action=level</kbd> (e.g. <kbd>edit=sysop</kbd>).\n\n<strong>Note:</strong> Any actions not listed will have restrictions removed.",
"apihelp-protect-param-expiry": "Expiry timestamps. If only one timestamp is set, it'll be used for all protections. Use <kbd>infinite</kbd>, <kbd>indefinite</kbd>, <kbd>infinity</kbd>, or <kbd>never</kbd>, for a never-expiring protection.",
"apihelp-protect-param-reason": "Reason for (un)protecting.",
"apihelp-protect-param-tags": "Change tags to apply to the entry in the protection log.",
"apihelp-protect-param-cascade": "Enable cascading protection (i.e. protect transcluded templates and images used in this page). Ignored if none of the given protection levels support cascading.",
"apihelp-protect-param-watch": "If set, add the page being (un)protected to the current user's watchlist.",
"apihelp-protect-param-watchlist": "Unconditionally add or remove the page from the current user's watchlist, use preferences or do not change watch.",
@ -1331,12 +1333,14 @@
"apihelp-unblock-param-id": "ID of the block to unblock (obtained through <kbd>list=blocks</kbd>). Cannot be used together with <var>$1user</var>.",
"apihelp-unblock-param-user": "Username, IP address or IP range to unblock. Cannot be used together with <var>$1id</var>.",
"apihelp-unblock-param-reason": "Reason for unblock.",
"apihelp-unblock-param-tags": "Change tags to apply to the entry in the block log.",
"apihelp-unblock-example-id": "Unblock block ID #<kbd>105</kbd>.",
"apihelp-unblock-example-user": "Unblock user <kbd>Bob</kbd> with reason <kbd>Sorry Bob</kbd>.",
"apihelp-undelete-description": "Restore revisions of a deleted page.\n\nA list of deleted revisions (including timestamps) can be retrieved through [[Special:ApiHelp/query+deletedrevs|list=deletedrevs]], and a list of deleted file IDs can be retrieved through [[Special:ApiHelp/query+filearchive|list=filearchive]].",
"apihelp-undelete-param-title": "Title of the page to restore.",
"apihelp-undelete-param-reason": "Reason for restoring.",
"apihelp-undelete-param-tags": "Change tags to apply to the entry in the deletion log.",
"apihelp-undelete-param-timestamps": "Timestamps of the revisions to restore. If both <var>$1timestamps</var> and <var>$1fileids</var> are empty, all will be restored.",
"apihelp-undelete-param-fileids": "IDs of the file revisions to restore. If both <var>$1timestamps</var> and <var>$1fileids</var> are empty, all will be restored.",
"apihelp-undelete-param-watchlist": "Unconditionally add or remove the page from the current user's watchlist, use preferences or do not change watch.",

View file

@ -325,6 +325,7 @@
"apihelp-patrol-description": "{{doc-apihelp-description|patrol}}",
"apihelp-patrol-param-rcid": "{{doc-apihelp-param|patrol|rcid}}",
"apihelp-patrol-param-revid": "{{doc-apihelp-param|patrol|revid}}",
"apihelp-patrol-param-tags": "{{doc-apihelp-param|patrol|tags}}",
"apihelp-patrol-example-rcid": "{{doc-apihelp-example|patrol}}",
"apihelp-patrol-example-revid": "{{doc-apihelp-example|patrol}}",
"apihelp-protect-description": "{{doc-apihelp-description|protect}}",
@ -333,6 +334,7 @@
"apihelp-protect-param-protections": "{{doc-apihelp-param|protect|protections}}",
"apihelp-protect-param-expiry": "{{doc-apihelp-param|protect|expiry}}",
"apihelp-protect-param-reason": "{{doc-apihelp-param|protect|reason}}",
"apihelp-protect-param-tags": "{{doc-apihelp-param|protect|tags}}",
"apihelp-protect-param-cascade": "{{doc-apihelp-param|protect|cascade}}",
"apihelp-protect-param-watch": "{{doc-apihelp-param|protect|watch}}",
"apihelp-protect-param-watchlist": "{{doc-apihelp-param|protect|watchlist}}",
@ -1240,11 +1242,13 @@
"apihelp-unblock-param-id": "{{doc-apihelp-param|unblock|id}}",
"apihelp-unblock-param-user": "{{doc-apihelp-param|unblock|user}}",
"apihelp-unblock-param-reason": "{{doc-apihelp-param|unblock|reason}}",
"apihelp-unblock-param-tags": "{{doc-apihelp-param|unblock|tags}}",
"apihelp-unblock-example-id": "{{doc-apihelp-example|unblock}}",
"apihelp-unblock-example-user": "{{doc-apihelp-example|unblock}}",
"apihelp-undelete-description": "{{doc-apihelp-description|undelete}}",
"apihelp-undelete-param-title": "{{doc-apihelp-param|undelete|title}}",
"apihelp-undelete-param-reason": "{{doc-apihelp-param|undelete|reason}}",
"apihelp-undelete-param-tags": "{{doc-apihelp-param|undelete|tags}}",
"apihelp-undelete-param-timestamps": "{{doc-apihelp-param|undelete|timestamps}}",
"apihelp-undelete-param-fileids": "{{doc-apihelp-param|undelete|fileids}}",
"apihelp-undelete-param-watchlist": "{{doc-apihelp-param|undelete|watchlist}}",

View file

@ -430,9 +430,11 @@ class RecentChange {
*
* @param RecentChange|int $change RecentChange or corresponding rc_id
* @param bool $auto For automatic patrol
* @param string|string[] $tags Change tags to add to the patrol log entry
* ($user should be able to add the specified tags before this is called)
* @return array See doMarkPatrolled(), or null if $change is not an existing rc_id
*/
public static function markPatrolled( $change, $auto = false ) {
public static function markPatrolled( $change, $auto = false, $tags = null ) {
global $wgUser;
$change = $change instanceof RecentChange
@ -443,7 +445,7 @@ class RecentChange {
return null;
}
return $change->doMarkPatrolled( $wgUser, $auto );
return $change->doMarkPatrolled( $wgUser, $auto, $tags );
}
/**
@ -453,9 +455,11 @@ class RecentChange {
* 'markedaspatrollederror-noautopatrol' as errors
* @param User $user User object doing the action
* @param bool $auto For automatic patrol
* @param string|string[] $tags Change tags to add to the patrol log entry
* ($user should be able to add the specified tags before this is called)
* @return array Array of permissions errors, see Title::getUserPermissionsErrors()
*/
public function doMarkPatrolled( User $user, $auto = false ) {
public function doMarkPatrolled( User $user, $auto = false, $tags = null ) {
global $wgUseRCPatrol, $wgUseNPPatrol, $wgUseFilePatrol;
$errors = [];
// If recentchanges patrol is disabled, only new pages or new file versions
@ -490,7 +494,8 @@ class RecentChange {
// Actually set the 'patrolled' flag in RC
$this->reallyMarkPatrolled();
// Log this patrol event
PatrolLog::record( $this, $auto, $user );
PatrolLog::record( $this, $auto, $user, $tags );
Hooks::run(
'MarkPatrolledComplete',
[ $this->getAttribute( 'rc_id' ), &$user, false, $auto ]

View file

@ -114,7 +114,7 @@ class ChangeTags {
/**
* Add tags to a change given its rc_id, rev_id and/or log_id
*
* @param string|array $tags Tags to add to the change
* @param string|string[] $tags Tags to add to the change
* @param int|null $rc_id The rc_id of the change to add the tags to
* @param int|null $rev_id The rev_id of the change to add the tags to
* @param int|null $log_id The log_id of the change to add the tags to

View file

@ -1479,18 +1479,14 @@ class LocalFile extends File {
__METHOD__
);
# Now that the log entry is up-to-date, make an RC entry.
$recentChange = $logEntry->publish( $logId );
# Add change tags, if any
if ( $tags ) {
ChangeTags::addTags(
$tags,
$recentChange ? $recentChange->getAttribute( 'rc_id' ) : null,
$logEntry->getAssociatedRevId(),
$logId
);
$logEntry->setTags( $tags );
}
# Now that the log entry is up-to-date, make an RC entry.
$logEntry->publish( $logId );
# Run hook for other updates (typically more cache purging)
Hooks::run( 'FileUpload', [ $that, $reupload, !$newPageContent ] );

View file

@ -419,6 +419,9 @@ class ManualLogEntry extends LogEntryBase {
/** @var int A rev id associated to the log entry */
protected $revId = 0;
/** @var array Change tags add to the log entry */
protected $tags = null;
/** @var int Deletion state of the log entry */
protected $deleted;
@ -529,6 +532,19 @@ class ManualLogEntry extends LogEntryBase {
$this->revId = $revId;
}
/**
* Set change tags for the log entry.
*
* @since 1.27
* @param string|string[] $tags
*/
public function setTags( $tags ) {
if ( is_string( $tags ) ) {
$tags = [ $tags ];
}
$this->tags = $tags;
}
/**
* Set the 'legacy' flag
*
@ -696,6 +712,14 @@ class ManualLogEntry extends LogEntryBase {
PatrolLog::record( $rc, true, $this->getPerformer() );
}
// Add change tags to the log entry and (if applicable) the associated revision
$tags = $this->getTags();
if ( !is_null( $tags ) ) {
$rcId = $rc->getAttribute( 'rc_id' );
$revId = $this->getAssociatedRevId(); // Use null if $revId is 0
ChangeTags::addTags( $tags, $rcId, $revId > 0 ? $revId : null, $newId );
}
return $rc;
}
@ -743,6 +767,14 @@ class ManualLogEntry extends LogEntryBase {
return $this->revId;
}
/**
* @since 1.27
* @return array
*/
public function getTags() {
return $this->tags;
}
/**
* @since 1.25
* @return bool

View file

@ -33,10 +33,12 @@ class PatrolLog {
* @param int|RecentChange $rc Change identifier or RecentChange object
* @param bool $auto Was this patrol event automatic?
* @param User $user User performing the action or null to use $wgUser
* @param string|string[] $tags Change tags to add to the patrol log entry
* ($user should be able to add the specified tags before this is called)
*
* @return bool
*/
public static function record( $rc, $auto = false, User $user = null ) {
public static function record( $rc, $auto = false, User $user = null, $tags = null ) {
global $wgLogAutopatrol;
// do not log autopatrolled edits if setting disables it
@ -60,6 +62,7 @@ class PatrolLog {
$entry->setTarget( $rc->getTitle() );
$entry->setParameters( self::buildParams( $rc, $auto ) );
$entry->setPerformer( $user );
$entry->setTags( $tags );
$logid = $entry->insert();
if ( !$auto ) {
$entry->publish( $logid, 'udp' );

View file

@ -2404,10 +2404,13 @@ class WikiPage implements Page, IDBAccessObject {
* @param int &$cascade Set to false if cascading protection isn't allowed.
* @param string $reason
* @param User $user The user updating the restrictions
* @return Status
* @param string|string[] $tags Change tags to add to the pages and protection log entries
* ($user should be able to add the specified tags before this is called)
* @return Status Status object; if action is taken, $status->value is the log_id of the
* protection log entry.
*/
public function doUpdateRestrictions( array $limit, array $expiry,
&$cascade, $reason, User $user
&$cascade, $reason, User $user, $tags = null
) {
global $wgCascadingRestrictionLevels, $wgContLang;
@ -2489,6 +2492,9 @@ class WikiPage implements Page, IDBAccessObject {
$logRelationsField = null;
$logParamsDetails = [];
// Null revision (used for change tag insertion)
$nullRevision = null;
if ( $id ) { // Protection of existing page
if ( !Hooks::run( 'ArticleProtect', [ &$this, &$user, $limit, $reason ] ) ) {
return Status::newGood();
@ -2632,13 +2638,17 @@ class WikiPage implements Page, IDBAccessObject {
$logEntry->setComment( $reason );
$logEntry->setPerformer( $user );
$logEntry->setParameters( $params );
if ( !is_null( $nullRevision ) ) {
$logEntry->setAssociatedRevId( $nullRevision->getId() );
}
$logEntry->setTags( $tags );
if ( $logRelationsField !== null && count( $logRelationsValues ) ) {
$logEntry->setRelations( [ $logRelationsField => $logRelationsValues ] );
}
$logId = $logEntry->insert();
$logEntry->publish( $logId );
return Status::newGood();
return Status::newGood( $logId );
}
/**

View file

@ -169,6 +169,9 @@ class SpecialUnblock extends SpecialPage {
/**
* Process the form
*
* Change tags can be provided via $data['Tags'], but the calling function
* must check if the tags can be added by the user prior to this function.
*
* @param array $data
* @param IContextSource $context
* @throws ErrorPageError
@ -235,6 +238,7 @@ class SpecialUnblock extends SpecialPage {
$logEntry->setTarget( $page );
$logEntry->setComment( $data['Reason'] );
$logEntry->setPerformer( $performer );
$logEntry->setTags( $data['Tags'] );
$logId = $logEntry->insert();
$logEntry->publish( $logId );

View file

@ -360,11 +360,13 @@ class PageArchive {
* @param array $fileVersions
* @param bool $unsuppress
* @param User $user User performing the action, or null to use $wgUser
* @param string|string[] $tags Change tags to add to log entry
* ($user should be able to add the specified tags before this is called)
* @return array(number of file revisions restored, number of image revisions
* restored, log message) on success, false on failure.
*/
function undelete( $timestamps, $comment = '', $fileVersions = [],
$unsuppress = false, User $user = null
$unsuppress = false, User $user = null, $tags = null
) {
// If both the set of text revisions and file revisions are empty,
// restore everything. Otherwise, just restore the requested items.
@ -426,6 +428,7 @@ class PageArchive {
$logEntry->setPerformer( $user );
$logEntry->setTarget( $this->title );
$logEntry->setComment( $reason );
$logEntry->setTags( $tags );
Hooks::run( 'ArticleUndeleteLogEntry', [ $this, &$logEntry, $user ] );