}
}
- $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 ) );
'revid' => [
ApiBase::PARAM_TYPE => 'integer'
],
+ 'tags' => [
+ ApiBase::PARAM_TYPE => 'tags',
+ ApiBase::PARAM_ISMULTI => true,
+ ],
];
}
$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 ) {
$expiryarray,
$cascade,
$params['reason'],
- $this->getUser()
+ $user,
+ $tags
);
if ( !$status->isOK() ) {
ApiBase::PARAM_DFLT => 'infinite',
],
'reason' => '',
+ 'tags' => [
+ ApiBase::PARAM_TYPE => 'tags',
+ ApiBase::PARAM_ISMULTI => true,
+ ],
'cascade' => false,
'watch' => [
ApiBase::PARAM_DFLT => false,
}
}
+ // 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() );
],
'user' => null,
'reason' => '',
+ 'tags' => [
+ ApiBase::PARAM_TYPE => 'tags',
+ ApiBase::PARAM_ISMULTI => true,
+ ],
];
}
$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'] = [];
$params['reason'],
$params['fileids'],
false,
- $this->getUser()
+ $user,
+ $params['tags']
);
if ( !is_array( $retval ) ) {
$this->dieUsageMsg( 'cannotundelete' );
ApiBase::PARAM_REQUIRED => true
],
'reason' => '',
+ 'tags' => [
+ ApiBase::PARAM_TYPE => 'tags',
+ ApiBase::PARAM_ISMULTI => true,
+ ],
'timestamps' => [
ApiBase::PARAM_TYPE => 'timestamp',
ApiBase::PARAM_ISMULTI => true,
"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.",
"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.",
"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.",
"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}}",
"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}}",
"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}}",
*
* @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
return null;
}
- return $change->doMarkPatrolled( $wgUser, $auto );
+ return $change->doMarkPatrolled( $wgUser, $auto, $tags );
}
/**
* '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
// 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 ]
/**
* 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
__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 ] );
/** @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;
$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
*
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;
}
return $this->revId;
}
+ /**
+ * @since 1.27
+ * @return array
+ */
+ public function getTags() {
+ return $this->tags;
+ }
+
/**
* @since 1.25
* @return bool
* @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
$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' );
* @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;
$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();
$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 );
}
/**
/**
* 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
$logEntry->setTarget( $page );
$logEntry->setComment( $data['Reason'] );
$logEntry->setPerformer( $performer );
+ $logEntry->setTags( $data['Tags'] );
$logId = $logEntry->insert();
$logEntry->publish( $logId );
* @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.
$logEntry->setPerformer( $user );
$logEntry->setTarget( $this->title );
$logEntry->setComment( $reason );
+ $logEntry->setTags( $tags );
Hooks::run( 'ArticleUndeleteLogEntry', [ $this, &$logEntry, $user ] );