Merge "Add tags support to patrol, protect, unblock, and undelete"
This commit is contained in:
commit
996b7350f3
14 changed files with 141 additions and 23 deletions
|
|
@ -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,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
|
|
@ -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}}",
|
||||
|
|
|
|||
|
|
@ -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 ]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ] );
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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' );
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ] );
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue