X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fchangetags%2FChangeTags.php;h=6455a3a980077de07beb0da2acae7de432fbf2ed;hb=9964ca1a390c446397dcd466916ffed356cdc3c9;hp=c8c50736d08a0e6fa054a812eca4700708816911;hpb=ba67060734ecfa835f54c83540c0c136db1690d7;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/changetags/ChangeTags.php b/includes/changetags/ChangeTags.php index c8c50736d0..bfabd51bcc 100644 --- a/includes/changetags/ChangeTags.php +++ b/includes/changetags/ChangeTags.php @@ -29,6 +29,11 @@ class ChangeTags { */ const MAX_DELETE_USES = 5000; + /** + * @var string[] + */ + private static $coreTags = [ 'mw-contentmodelchange' ]; + /** * Creates HTML for the given tags * @@ -58,7 +63,7 @@ class ChangeTags { if ( !$tag ) { continue; } - $description = self::tagDescription( $tag ); + $description = self::tagDescription( $tag, $context ); if ( $description === false ) { continue; } @@ -93,11 +98,12 @@ class ChangeTags { * we consider the tag hidden, and return false. * * @param string $tag Tag + * @param IContextSource $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 ) { - $msg = wfMessage( "tag-$tag" ); + public static function tagDescription( $tag, IContextSource $context ) { + $msg = $context->msg( "tag-$tag" ); if ( !$msg->exists() ) { // No such message, so return the HTML-escaped tag name. return htmlspecialchars( $tag ); @@ -119,14 +125,16 @@ class ChangeTags { * @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 * @param string $params Params to put in the ct_params field of table 'change_tag' + * @param RecentChange|null $rc Recent change, in case the tagging accompanies the action + * (this should normally be the case) * * @throws MWException * @return bool False if no changes are made, otherwise true */ public static function addTags( $tags, $rc_id = null, $rev_id = null, - $log_id = null, $params = null + $log_id = null, $params = null, RecentChange $rc = null ) { - $result = self::updateTags( $tags, null, $rc_id, $rev_id, $log_id, $params ); + $result = self::updateTags( $tags, null, $rc_id, $rev_id, $log_id, $params, $rc ); return (bool)$result[0]; } @@ -149,6 +157,9 @@ class ChangeTags { * Pass a variable whose value is null if the log_id is not relevant or unknown. * @param string $params Params to put in the ct_params field of table * 'change_tag' when adding tags + * @param RecentChange|null $rc Recent change being tagged, in case the tagging accompanies + * the action + * @param User|null $user Tagging user, in case the tagging is subsequent to the tagged action * * @throws MWException When $rc_id, $rev_id and $log_id are all null * @return array Index 0 is an array of tags actually added, index 1 is an @@ -157,9 +168,9 @@ class ChangeTags { * * @since 1.25 */ - public static function updateTags( - $tagsToAdd, $tagsToRemove, - &$rc_id = null, &$rev_id = null, &$log_id = null, $params = null + public static function updateTags( $tagsToAdd, $tagsToRemove, &$rc_id = null, + &$rev_id = null, &$log_id = null, $params = null, RecentChange $rc = null, + User $user = null ) { $tagsToAdd = array_filter( (array)$tagsToAdd ); // Make sure we're submitting all tags... @@ -279,6 +290,10 @@ class ChangeTags { } self::purgeTagUsageCache(); + + Hooks::run( 'ChangeTagsAfterUpdateTags', [ $tagsToAdd, $tagsToRemove, $prevTags, + $rc_id, $rev_id, $log_id, $params, $rc, $user ] ); + return [ $tagsToAdd, $tagsToRemove, $prevTags ]; } @@ -382,7 +397,7 @@ class ChangeTags { if ( !$user->isAllowed( 'applychangetags' ) ) { return Status::newFatal( 'tags-apply-no-permission' ); } elseif ( $user->isBlocked() ) { - return Status::newFatal( 'tags-apply-blocked' ); + return Status::newFatal( 'tags-apply-blocked', $user->getName() ); } } @@ -453,7 +468,7 @@ class ChangeTags { if ( !$user->isAllowed( 'changetags' ) ) { return Status::newFatal( 'tags-update-no-permission' ); } elseif ( $user->isBlocked() ) { - return Status::newFatal( 'tags-update-blocked' ); + return Status::newFatal( 'tags-update-blocked', $user->getName() ); } } @@ -472,8 +487,8 @@ class ChangeTags { // to be removed, a tag must not be defined by an extension, or equivalently it // has to be either explicitly defined or not defined at all // (assuming no edge case of a tag both explicitly-defined and extension-defined) - $extensionDefinedTags = self::listExtensionDefinedTags(); - $intersect = array_intersect( $tagsToRemove, $extensionDefinedTags ); + $softwareDefinedTags = self::listSoftwareDefinedTags(); + $intersect = array_intersect( $tagsToRemove, $softwareDefinedTags ); if ( $intersect ) { return self::restrictedTagError( 'tags-update-remove-not-allowed-one', 'tags-update-remove-not-allowed-multi', $intersect ); @@ -541,7 +556,7 @@ class ChangeTags { // do it! list( $tagsAdded, $tagsRemoved, $initialTags ) = self::updateTags( $tagsToAdd, - $tagsToRemove, $rc_id, $rev_id, $log_id, $params ); + $tagsToRemove, $rc_id, $rev_id, $log_id, $params, null, $user ); if ( !$tagsAdded && !$tagsRemoved ) { // no-op, don't log it return Status::newGood( (object)[ @@ -566,7 +581,7 @@ class ChangeTags { // This function is from revision deletion logic and has nothing to do with // change tags, but it appears to be the only other place in core where we // perform logged actions on log items. - $logEntry->setTarget( RevDelLogList::suggestTarget( 0, [ $log_id ] ) ); + $logEntry->setTarget( RevDelLogList::suggestTarget( null, [ $log_id ] ) ); } if ( !$logEntry->getTarget() ) { @@ -603,10 +618,10 @@ class ChangeTags { * Handles selecting tags, and filtering. * Needs $tables to be set up properly, so we can figure out which join conditions to use. * - * @param string|array $tables Table names, see DatabaseBase::select - * @param string|array $fields Fields used in query, see DatabaseBase::select - * @param string|array $conds Conditions used in query, see DatabaseBase::select - * @param array $join_conds Join conditions, see DatabaseBase::select + * @param string|array $tables Table names, see Database::select + * @param string|array $fields Fields used in query, see Database::select + * @param string|array $conds Conditions used in query, see Database::select + * @param array $join_conds Join conditions, see Database::select * @param array $options Options, see Database::select * @param bool|string $filter_tag Tag to select on * @@ -651,28 +666,30 @@ class ChangeTags { * Build a text box to select a change tag * * @param string $selected Tag to select by default - * @param bool $fullForm Affects return value, see below - * @param Title $title Title object to send the form to. Used only if $fullForm is true. * @param bool $ooui Use an OOUI TextInputWidget as selector instead of a non-OOUI input field * You need to call OutputPage::enableOOUI() yourself. - * @return string|array - * - if $fullForm is false: an array of (label, selector). - * - if $fullForm is true: HTML of entire form built around the selector. + * @param IContextSource|null $context + * @note Even though it takes null as a valid argument, an IContextSource is preferred + * in a new code, as the null value can change in the future + * @return array an array of (label, selector) */ - public static function buildTagFilterSelector( $selected = '', - $fullForm = false, Title $title = null, $ooui = false + public static function buildTagFilterSelector( + $selected = '', $ooui = false, IContextSource $context = null ) { - global $wgUseTagFilter; + if ( !$context ) { + $context = RequestContext::getMain(); + } - if ( !$wgUseTagFilter || !count( self::listDefinedTags() ) ) { - return $fullForm ? '' : []; + $config = $context->getConfig(); + if ( !$config->get( 'UseTagFilter' ) || !count( self::listDefinedTags() ) ) { + return []; } $data = [ Html::rawElement( 'label', [ 'for' => 'tagfilter' ], - wfMessage( 'tag-filter' )->parse() + $context->msg( 'tag-filter' )->parse() ) ]; @@ -692,24 +709,7 @@ class ChangeTags { ); } - if ( !$fullForm ) { - return $data; - } - - $html = implode( ' ', $data ); - $html .= "\n" . - Xml::element( - 'input', - [ 'type' => 'submit', 'value' => wfMessage( 'tag-filter-submit' )->text() ] - ); - $html .= "\n" . Html::hidden( 'title', $title->getPrefixedText() ); - $html = Xml::tags( - 'form', - [ 'action' => $title->getLocalURL(), 'class' => 'mw-tagfilter-form', 'method' => 'get' ], - $html - ); - - return $html; + return $data; } /** @@ -798,7 +798,7 @@ class ChangeTags { if ( !$user->isAllowed( 'managechangetags' ) ) { return Status::newFatal( 'tags-manage-no-permission' ); } elseif ( $user->isBlocked() ) { - return Status::newFatal( 'tags-manage-blocked' ); + return Status::newFatal( 'tags-manage-blocked', $user->getName() ); } } @@ -866,7 +866,7 @@ class ChangeTags { if ( !$user->isAllowed( 'managechangetags' ) ) { return Status::newFatal( 'tags-manage-no-permission' ); } elseif ( $user->isBlocked() ) { - return Status::newFatal( 'tags-manage-blocked' ); + return Status::newFatal( 'tags-manage-blocked', $user->getName() ); } } @@ -925,7 +925,7 @@ class ChangeTags { if ( !$user->isAllowed( 'managechangetags' ) ) { return Status::newFatal( 'tags-manage-no-permission' ); } elseif ( $user->isBlocked() ) { - return Status::newFatal( 'tags-manage-blocked' ); + return Status::newFatal( 'tags-manage-blocked', $user->getName() ); } } @@ -1033,7 +1033,7 @@ class ChangeTags { // let's not allow error results, as the actual tag deletion succeeded if ( !$status->isOK() ) { wfDebug( 'ChangeTagAfterDelete error condition downgraded to warning' ); - $status->ok = true; + $status->setOK( true ); } // clear the memcache of defined tags @@ -1058,7 +1058,7 @@ class ChangeTags { if ( !$user->isAllowed( 'deletechangetags' ) ) { return Status::newFatal( 'tags-delete-no-permission' ); } elseif ( $user->isBlocked() ) { - return Status::newFatal( 'tags-manage-blocked' ); + return Status::newFatal( 'tags-manage-blocked', $user->getName() ); } } @@ -1070,8 +1070,8 @@ class ChangeTags { return Status::newFatal( 'tags-delete-too-many-uses', $tag, self::MAX_DELETE_USES ); } - $extensionDefined = self::listExtensionDefinedTags(); - if ( in_array( $tag, $extensionDefined ) ) { + $softwareDefined = self::listSoftwareDefinedTags(); + if ( in_array( $tag, $softwareDefined ) ) { // extension-defined tags can't be deleted unless the extension // specifically allows it $status = Status::newFatal( 'tags-delete-not-allowed' ); @@ -1126,22 +1126,26 @@ class ChangeTags { } /** - * Lists those tags which extensions report as being "active". + * Lists those tags which core or extensions report as being "active". * * @return array * @since 1.25 */ - public static function listExtensionActivatedTags() { + public static function listSoftwareActivatedTags() { + // core active tags + $tags = self::$coreTags; + if ( !Hooks::isRegistered( 'ChangeTagsListActive' ) ) { + return $tags; + } return ObjectCache::getMainWANInstance()->getWithSetCallback( wfMemcKey( 'active-tags' ), WANObjectCache::TTL_MINUTE * 5, - function ( $oldValue, &$ttl, array &$setOpts ) { + function ( $oldValue, &$ttl, array &$setOpts ) use ( $tags ) { $setOpts += Database::getCacheSetOptions( wfGetDB( DB_REPLICA ) ); // Ask extensions which tags they consider active - $extensionActive = []; - Hooks::run( 'ChangeTagsListActive', [ &$extensionActive ] ); - return $extensionActive; + Hooks::run( 'ChangeTagsListActive', [ &$tags ] ); + return $tags; }, [ 'checkKeys' => [ wfMemcKey( 'active-tags' ) ], @@ -1151,6 +1155,16 @@ class ChangeTags { ); } + /** + * @see listSoftwareActivatedTags + * @deprecated since 1.28 call listSoftwareActivatedTags directly + * @return array + */ + public static function listExtensionActivatedTags() { + wfDeprecated( __METHOD__, '1.28' ); + return self::listSoftwareActivatedTags(); + } + /** * Basically lists defined tags which count even if they aren't applied to anything. * It returns a union of the results of listExplicitlyDefinedTags() and @@ -1160,7 +1174,7 @@ class ChangeTags { */ public static function listDefinedTags() { $tags1 = self::listExplicitlyDefinedTags(); - $tags2 = self::listExtensionDefinedTags(); + $tags2 = self::listSoftwareDefinedTags(); return array_values( array_unique( array_merge( $tags1, $tags2 ) ) ); } @@ -1198,7 +1212,7 @@ class ChangeTags { } /** - * Lists tags defined by extensions using the ListDefinedTags hook. + * Lists tags defined by core or extensions using the ListDefinedTags hook. * Extensions need only define those tags they deem to be in active use. * * Tries memcached first. @@ -1206,14 +1220,18 @@ class ChangeTags { * @return string[] Array of strings: tags * @since 1.25 */ - public static function listExtensionDefinedTags() { + public static function listSoftwareDefinedTags() { + // core defined tags + $tags = self::$coreTags; + if ( !Hooks::isRegistered( 'ListDefinedTags' ) ) { + return $tags; + } return ObjectCache::getMainWANInstance()->getWithSetCallback( wfMemcKey( 'valid-tags-hook' ), WANObjectCache::TTL_MINUTE * 5, - function ( $oldValue, &$ttl, array &$setOpts ) { + function ( $oldValue, &$ttl, array &$setOpts ) use ( $tags ) { $setOpts += Database::getCacheSetOptions( wfGetDB( DB_REPLICA ) ); - $tags = []; Hooks::run( 'ListDefinedTags', [ &$tags ] ); return array_filter( array_unique( $tags ) ); }, @@ -1225,6 +1243,17 @@ class ChangeTags { ); } + /** + * Call listSoftwareDefinedTags directly + * + * @see listSoftwareDefinedTags + * @deprecated since 1.28 + */ + public static function listExtensionDefinedTags() { + wfDeprecated( __METHOD__, '1.28' ); + return self::listSoftwareDefinedTags(); + } + /** * Invalidates the short-term cache of defined tags used by the * list*DefinedTags functions, as well as the tag statistics cache.