* @ingroup Change tagging
*/
+use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\Database;
+
class ChangeTags {
/**
* Can't delete tags with more than this many uses. Similar in intent to
}
// to be applied, a tag has to be explicitly defined
- // @todo Allow extensions to define tags that can be applied by users...
$allowedTags = self::listExplicitlyDefinedTags();
+ Hooks::run( 'ChangeTagsAllowedAdd', [ &$allowedTags, $tags, $user ] );
$disallowedTags = array_diff( $tags, $allowedTags );
if ( $disallowedTags ) {
return self::restrictedTagError( 'tags-apply-not-allowed-one',
$tables[] = 'change_tag';
$join_conds['change_tag'] = [ 'INNER JOIN', $join_cond ];
- $conds['ct_tag'] = $filter_tag;
+ $conds['ct_tag'] = explode( '|', $filter_tag );
}
}
* @param User $user Who to attribute the action to
* @param int $tagCount For deletion only, how many usages the tag had before
* it was deleted.
+ * @param array $logEntryTags Change tags to apply to the entry
+ * that will be created in the tag management log
* @return int ID of the inserted log entry
* @since 1.25
*/
protected static function logTagManagementAction( $action, $tag, $reason,
- User $user, $tagCount = null ) {
+ User $user, $tagCount = null, array $logEntryTags = [] ) {
$dbw = wfGetDB( DB_MASTER );
}
$logEntry->setParameters( $params );
$logEntry->setRelations( [ 'Tag' => $tag ] );
+ $logEntry->setTags( $logEntryTags );
$logId = $logEntry->insert( $dbw );
$logEntry->publish( $logId );
* @param string $reason
* @param User $user Who to give credit for the action
* @param bool $ignoreWarnings Can be used for API interaction, default false
+ * @param array $logEntryTags Change tags to apply to the entry
+ * that will be created in the tag management log
* @return Status If successful, the Status contains the ID of the added log
* entry as its value
* @since 1.25
*/
public static function activateTagWithChecks( $tag, $reason, User $user,
- $ignoreWarnings = false ) {
+ $ignoreWarnings = false, array $logEntryTags = [] ) {
// are we allowed to do this?
$result = self::canActivateTag( $tag, $user );
self::defineTag( $tag );
// log it
- $logId = self::logTagManagementAction( 'activate', $tag, $reason, $user );
+ $logId = self::logTagManagementAction( 'activate', $tag, $reason, $user,
+ null, $logEntryTags );
+
return Status::newGood( $logId );
}
* @param string $reason
* @param User $user Who to give credit for the action
* @param bool $ignoreWarnings Can be used for API interaction, default false
+ * @param array $logEntryTags Change tags to apply to the entry
+ * that will be created in the tag management log
* @return Status If successful, the Status contains the ID of the added log
* entry as its value
* @since 1.25
*/
public static function deactivateTagWithChecks( $tag, $reason, User $user,
- $ignoreWarnings = false ) {
+ $ignoreWarnings = false, array $logEntryTags = [] ) {
// are we allowed to do this?
$result = self::canDeactivateTag( $tag, $user );
self::undefineTag( $tag );
// log it
- $logId = self::logTagManagementAction( 'deactivate', $tag, $reason, $user );
+ $logId = self::logTagManagementAction( 'deactivate', $tag, $reason, $user,
+ null, $logEntryTags );
+
return Status::newGood( $logId );
}
+ /**
+ * Is the tag name valid?
+ *
+ * @param string $tag Tag that you are interested in creating
+ * @return Status
+ * @since 1.30
+ */
+ public static function isTagNameValid( $tag ) {
+ // no empty tags
+ if ( $tag === '' ) {
+ return Status::newFatal( 'tags-create-no-name' );
+ }
+
+ // tags cannot contain commas (used as a delimiter in tag_summary table),
+ // pipe (used as a delimiter between multiple tags in
+ // modifyDisplayQuery), or slashes (would break tag description messages in
+ // MediaWiki namespace)
+ if ( strpos( $tag, ',' ) !== false || strpos( $tag, '|' ) !== false
+ || strpos( $tag, '/' ) !== false ) {
+ return Status::newFatal( 'tags-create-invalid-chars' );
+ }
+
+ // could the MediaWiki namespace description messages be created?
+ $title = Title::makeTitleSafe( NS_MEDIAWIKI, "Tag-$tag-description" );
+ if ( is_null( $title ) ) {
+ return Status::newFatal( 'tags-create-invalid-title-chars' );
+ }
+
+ return Status::newGood();
+ }
+
/**
* Is it OK to allow the user to create this tag?
*
}
}
- // no empty tags
- if ( $tag === '' ) {
- return Status::newFatal( 'tags-create-no-name' );
- }
-
- // tags cannot contain commas (used as a delimiter in tag_summary table) or
- // slashes (would break tag description messages in MediaWiki namespace)
- if ( strpos( $tag, ',' ) !== false || strpos( $tag, '/' ) !== false ) {
- return Status::newFatal( 'tags-create-invalid-chars' );
- }
-
- // could the MediaWiki namespace description messages be created?
- $title = Title::makeTitleSafe( NS_MEDIAWIKI, "Tag-$tag-description" );
- if ( is_null( $title ) ) {
- return Status::newFatal( 'tags-create-invalid-title-chars' );
+ $status = self::isTagNameValid( $tag );
+ if ( !$status->isGood() ) {
+ return $status;
}
// does the tag already exist?
* @param string $reason
* @param User $user Who to give credit for the action
* @param bool $ignoreWarnings Can be used for API interaction, default false
+ * @param array $logEntryTags Change tags to apply to the entry
+ * that will be created in the tag management log
* @return Status If successful, the Status contains the ID of the added log
* entry as its value
* @since 1.25
*/
public static function createTagWithChecks( $tag, $reason, User $user,
- $ignoreWarnings = false ) {
+ $ignoreWarnings = false, array $logEntryTags = [] ) {
// are we allowed to do this?
$result = self::canCreateTag( $tag, $user );
self::defineTag( $tag );
// log it
- $logId = self::logTagManagementAction( 'create', $tag, $reason, $user );
+ $logId = self::logTagManagementAction( 'create', $tag, $reason, $user,
+ null, $logEntryTags );
+
return Status::newGood( $logId );
}
* @param string $reason
* @param User $user Who to give credit for the action
* @param bool $ignoreWarnings Can be used for API interaction, default false
+ * @param array $logEntryTags Change tags to apply to the entry
+ * that will be created in the tag management log
* @return Status If successful, the Status contains the ID of the added log
* entry as its value
* @since 1.25
*/
public static function deleteTagWithChecks( $tag, $reason, User $user,
- $ignoreWarnings = false ) {
+ $ignoreWarnings = false, array $logEntryTags = [] ) {
// are we allowed to do this?
$result = self::canDeleteTag( $tag, $user );
}
// log it
- $logId = self::logTagManagementAction( 'delete', $tag, $reason, $user, $hitcount );
+ $logId = self::logTagManagementAction( 'delete', $tag, $reason, $user,
+ $hitcount, $logEntryTags );
+
$deleteResult->value = $logId;
return $deleteResult;
}
if ( !Hooks::isRegistered( 'ChangeTagsListActive' ) ) {
return $tags;
}
- return ObjectCache::getMainWANInstance()->getWithSetCallback(
- wfMemcKey( 'active-tags' ),
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+ return $cache->getWithSetCallback(
+ $cache->makeKey( 'active-tags' ),
WANObjectCache::TTL_MINUTE * 5,
function ( $oldValue, &$ttl, array &$setOpts ) use ( $tags ) {
$setOpts += Database::getCacheSetOptions( wfGetDB( DB_REPLICA ) );
return $tags;
},
[
- 'checkKeys' => [ wfMemcKey( 'active-tags' ) ],
+ 'checkKeys' => [ $cache->makeKey( 'active-tags' ) ],
'lockTSE' => WANObjectCache::TTL_MINUTE * 5,
'pcTTL' => WANObjectCache::TTL_PROC_LONG
]
public static function listExplicitlyDefinedTags() {
$fname = __METHOD__;
- return ObjectCache::getMainWANInstance()->getWithSetCallback(
- wfMemcKey( 'valid-tags-db' ),
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+ return $cache->getWithSetCallback(
+ $cache->makeKey( 'valid-tags-db' ),
WANObjectCache::TTL_MINUTE * 5,
function ( $oldValue, &$ttl, array &$setOpts ) use ( $fname ) {
$dbr = wfGetDB( DB_REPLICA );
return array_filter( array_unique( $tags ) );
},
[
- 'checkKeys' => [ wfMemcKey( 'valid-tags-db' ) ],
+ 'checkKeys' => [ $cache->makeKey( 'valid-tags-db' ) ],
'lockTSE' => WANObjectCache::TTL_MINUTE * 5,
'pcTTL' => WANObjectCache::TTL_PROC_LONG
]
if ( !Hooks::isRegistered( 'ListDefinedTags' ) ) {
return $tags;
}
- return ObjectCache::getMainWANInstance()->getWithSetCallback(
- wfMemcKey( 'valid-tags-hook' ),
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+ return $cache->getWithSetCallback(
+ $cache->makeKey( 'valid-tags-hook' ),
WANObjectCache::TTL_MINUTE * 5,
function ( $oldValue, &$ttl, array &$setOpts ) use ( $tags ) {
$setOpts += Database::getCacheSetOptions( wfGetDB( DB_REPLICA ) );
return array_filter( array_unique( $tags ) );
},
[
- 'checkKeys' => [ wfMemcKey( 'valid-tags-hook' ) ],
+ 'checkKeys' => [ $cache->makeKey( 'valid-tags-hook' ) ],
'lockTSE' => WANObjectCache::TTL_MINUTE * 5,
'pcTTL' => WANObjectCache::TTL_PROC_LONG
]
* @since 1.25
*/
public static function purgeTagCacheAll() {
- $cache = ObjectCache::getMainWANInstance();
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
- $cache->touchCheckKey( wfMemcKey( 'active-tags' ) );
- $cache->touchCheckKey( wfMemcKey( 'valid-tags-db' ) );
- $cache->touchCheckKey( wfMemcKey( 'valid-tags-hook' ) );
+ $cache->touchCheckKey( $cache->makeKey( 'active-tags' ) );
+ $cache->touchCheckKey( $cache->makeKey( 'valid-tags-db' ) );
+ $cache->touchCheckKey( $cache->makeKey( 'valid-tags-hook' ) );
self::purgeTagUsageCache();
}
* @since 1.25
*/
public static function purgeTagUsageCache() {
- $cache = ObjectCache::getMainWANInstance();
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
- $cache->touchCheckKey( wfMemcKey( 'change-tag-statistics' ) );
+ $cache->touchCheckKey( $cache->makeKey( 'change-tag-statistics' ) );
}
/**
*/
public static function tagUsageStatistics() {
$fname = __METHOD__;
- return ObjectCache::getMainWANInstance()->getWithSetCallback(
- wfMemcKey( 'change-tag-statistics' ),
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+ return $cache->getWithSetCallback(
+ $cache->makeKey( 'change-tag-statistics' ),
WANObjectCache::TTL_MINUTE * 5,
function ( $oldValue, &$ttl, array &$setOpts ) use ( $fname ) {
$dbr = wfGetDB( DB_REPLICA, 'vslow' );
return $out;
},
[
- 'checkKeys' => [ wfMemcKey( 'change-tag-statistics' ) ],
+ 'checkKeys' => [ $cache->makeKey( 'change-tag-statistics' ) ],
'lockTSE' => WANObjectCache::TTL_MINUTE * 5,
'pcTTL' => WANObjectCache::TTL_PROC_LONG
]