use MediaWiki\MediaWikiServices;
use MediaWiki\Storage\NameTableAccessException;
use Wikimedia\Rdbms\Database;
+use Wikimedia\Rdbms\IDatabase;
class ChangeTags {
/**
$markers = $context->msg( 'tag-list-wrapper' )
->numParams( count( $displayTags ) )
- ->rawParams( $context->getLanguage()->commaList( $displayTags ) )
+ ->rawParams( implode( ' ', $displayTags ) )
->parse();
$markers = Xml::tags( 'span', [ 'class' => 'mw-tag-markers' ], $markers );
}
/**
- * Get a short description for a tag.
+ * Get the message object for the tag's short description.
*
* Checks if message key "mediawiki:tag-$tag" exists. If it does not,
- * returns the HTML-escaped tag name. Uses the message if the message
- * exists, provided it is not disabled. If the message is disabled,
- * we consider the tag hidden, and return false.
+ * returns the tag name in a RawMessage. If the message exists, it is
+ * used, provided it is not disabled. If the message is disabled, we
+ * consider the tag hidden, and return false.
*
+ * @since 1.34
* @param string $tag
* @param MessageLocalizer $context
- * @return string|bool Tag description or false if tag is to be hidden.
- * @since 1.25 Returns false if tag is to be hidden.
+ * @return Message|bool Tag description, or false if tag is to be hidden.
*/
- public static function tagDescription( $tag, MessageLocalizer $context ) {
+ public static function tagShortDescriptionMessage( $tag, MessageLocalizer $context ) {
$msg = $context->msg( "tag-$tag" );
if ( !$msg->exists() ) {
- // No such message, so return the HTML-escaped tag name.
- return htmlspecialchars( $tag );
+ // No such message
+ return ( new RawMessage( '$1', [ Message::plaintextParam( $tag ) ] ) )
+ // HACK MessageLocalizer doesn't have a way to set the right language on a RawMessage,
+ // so extract the language from $msg and use that.
+ // The language doesn't really matter, but we need to set it to avoid requesting
+ // the user's language from session-less entry points (T227233)
+ ->inLanguage( $msg->getLanguage() );
+
}
if ( $msg->isDisabled() ) {
// The message exists but is disabled, hide the tag.
}
// Message exists and isn't disabled, use it.
- return $msg->parse();
+ return $msg;
+ }
+
+ /**
+ * Get a short description for a tag.
+ *
+ * Checks if message key "mediawiki:tag-$tag" exists. If it does not,
+ * returns the HTML-escaped tag name. Uses the message if the message
+ * exists, provided it is not disabled. If the message is disabled,
+ * we consider the tag hidden, and return false.
+ *
+ * @param string $tag
+ * @param MessageLocalizer $context
+ * @return string|bool Tag description or false if tag is to be hidden.
+ * @since 1.25 Returns false if tag is to be hidden.
+ */
+ public static function tagDescription( $tag, MessageLocalizer $context ) {
+ $msg = self::tagShortDescriptionMessage( $tag, $context );
+ return $msg ? $msg->parse() : false;
}
/**
);
}
- $prevTags = self::getPrevTags( $rc_id, $log_id, $rev_id );
+ $prevTags = self::getTags( $dbw, $rc_id, $rev_id, $log_id );
// add tags
$tagsToAdd = array_values( array_diff( $tagsToAdd, $prevTags ) );
return [ $tagsToAdd, $tagsToRemove, $prevTags ];
}
- private static function getPrevTags( $rc_id = null, $log_id = null, $rev_id = null ) {
+ /**
+ * Return all the tags associated with the given recent change ID,
+ * revision ID, and/or log entry ID.
+ *
+ * @param IDatabase $db the database to query
+ * @param int|null $rc_id
+ * @param int|null $rev_id
+ * @param int|null $log_id
+ * @return string[]
+ */
+ public static function getTags( IDatabase $db, $rc_id = null, $rev_id = null, $log_id = null ) {
$conds = array_filter(
[
'ct_rc_id' => $rc_id,
- 'ct_log_id' => $log_id,
'ct_rev_id' => $rev_id,
+ 'ct_log_id' => $log_id,
]
);
- $dbw = wfGetDB( DB_MASTER );
- $tagIds = $dbw->selectFieldValues( 'change_tag', 'ct_tag_id', $conds, __METHOD__ );
+ $tagIds = $db->selectFieldValues(
+ 'change_tag',
+ 'ct_tag_id',
+ $conds,
+ __METHOD__
+ );
$tags = [];
+ $changeTagDefStore = MediaWikiServices::getInstance()->getChangeTagDefStore();
foreach ( $tagIds as $tagId ) {
- $tags[] = MediaWikiServices::getInstance()->getChangeTagDefStore()->getName( (int)$tagId );
+ $tags[] = $changeTagDefStore->getName( (int)$tagId );
}
return $tags;
*/
public static function canAddTagsAccompanyingChange( array $tags, User $user = null ) {
if ( !is_null( $user ) ) {
- if ( !$user->isAllowed( 'applychangetags' ) ) {
+ if ( !MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'applychangetags' )
+ ) {
return Status::newFatal( 'tags-apply-no-permission' );
} elseif ( $user->getBlock() ) {
// @TODO Ensure that the block does not apply to the `applychangetags`
User $user = null
) {
if ( !is_null( $user ) ) {
- if ( !$user->isAllowed( 'changetags' ) ) {
+ if ( !MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'changetags' )
+ ) {
return Status::newFatal( 'tags-update-no-permission' );
} elseif ( $user->getBlock() ) {
// @TODO Ensure that the block does not apply to the `changetags`
*/
public static function canActivateTag( $tag, User $user = null ) {
if ( !is_null( $user ) ) {
- if ( !$user->isAllowed( 'managechangetags' ) ) {
+ if ( !MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'managechangetags' )
+ ) {
return Status::newFatal( 'tags-manage-no-permission' );
} elseif ( $user->getBlock() ) {
// @TODO Ensure that the block does not apply to the `managechangetags`
*/
public static function canDeactivateTag( $tag, User $user = null ) {
if ( !is_null( $user ) ) {
- if ( !$user->isAllowed( 'managechangetags' ) ) {
+ if ( !MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'managechangetags' )
+ ) {
return Status::newFatal( 'tags-manage-no-permission' );
} elseif ( $user->getBlock() ) {
// @TODO Ensure that the block does not apply to the `managechangetags`
*/
public static function canCreateTag( $tag, User $user = null ) {
if ( !is_null( $user ) ) {
- if ( !$user->isAllowed( 'managechangetags' ) ) {
+ if ( !MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'managechangetags' )
+ ) {
return Status::newFatal( 'tags-manage-no-permission' );
} elseif ( $user->getBlock() ) {
// @TODO Ensure that the block does not apply to the `managechangetags`
$tagUsage = self::tagUsageStatistics();
if ( !is_null( $user ) ) {
- if ( !$user->isAllowed( 'deletechangetags' ) ) {
+ if ( !MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'deletechangetags' )
+ ) {
return Status::newFatal( 'tags-delete-no-permission' );
} elseif ( $user->getBlock() ) {
// @TODO Ensure that the block does not apply to the `deletechangetags`
$cache->touchCheckKey( $cache->makeKey( 'active-tags' ) );
$cache->touchCheckKey( $cache->makeKey( 'valid-tags-db' ) );
$cache->touchCheckKey( $cache->makeKey( 'valid-tags-hook' ) );
+ $cache->touchCheckKey( $cache->makeKey( 'tags-usage-statistics' ) );
MediaWikiServices::getInstance()->getChangeTagDefStore()->reloadMap();
}
* @return array Array of string => int
*/
public static function tagUsageStatistics() {
- $dbr = wfGetDB( DB_REPLICA );
- $res = $dbr->select(
- 'change_tag_def',
- [ 'ctd_name', 'ctd_count' ],
- [],
- __METHOD__,
- [ 'ORDER BY' => 'ctd_count DESC' ]
- );
+ $fname = __METHOD__;
- $out = [];
- foreach ( $res as $row ) {
- $out[$row->ctd_name] = $row->ctd_count;
- }
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+ return $cache->getWithSetCallback(
+ $cache->makeKey( 'tags-usage-statistics' ),
+ WANObjectCache::TTL_MINUTE * 5,
+ function ( $oldValue, &$ttl, array &$setOpts ) use ( $fname ) {
+ $dbr = wfGetDB( DB_REPLICA );
+ $res = $dbr->select(
+ 'change_tag_def',
+ [ 'ctd_name', 'ctd_count' ],
+ [],
+ $fname,
+ [ 'ORDER BY' => 'ctd_count DESC' ]
+ );
+
+ $out = [];
+ foreach ( $res as $row ) {
+ $out[$row->ctd_name] = $row->ctd_count;
+ }
- return $out;
+ return $out;
+ },
+ [
+ 'checkKeys' => [ $cache->makeKey( 'tags-usage-statistics' ) ],
+ 'lockTSE' => WANObjectCache::TTL_MINUTE * 5,
+ 'pcTTL' => WANObjectCache::TTL_PROC_LONG
+ ]
+ );
}
/**
* @return bool
*/
public static function showTagEditingUI( User $user ) {
- return $user->isAllowed( 'changetags' ) && (bool)self::listExplicitlyDefinedTags();
+ return MediaWikiServices::getInstance()->getPermissionManager()
+ ->userHasRight( $user, 'changetags' ) &&
+ (bool)self::listExplicitlyDefinedTags();
}
}