diff options
Diffstat (limited to 'Thanks/includes/ThanksHooks.php')
-rw-r--r-- | Thanks/includes/ThanksHooks.php | 180 |
1 files changed, 91 insertions, 89 deletions
diff --git a/Thanks/includes/ThanksHooks.php b/Thanks/includes/ThanksHooks.php index d2308a1a..34cadd69 100644 --- a/Thanks/includes/ThanksHooks.php +++ b/Thanks/includes/ThanksHooks.php @@ -1,6 +1,9 @@ <?php +use MediaWiki\Linker\LinkTarget; use MediaWiki\MediaWikiServices; +use MediaWiki\Revision\RevisionRecord; +use MediaWiki\User\UserIdentity; /** * Hooks for Thanks extension @@ -11,43 +14,35 @@ use MediaWiki\MediaWikiServices; class ThanksHooks { /** - * ResourceLoaderTestModules hook handler - * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderTestModules + * Handler for HistoryTools and DiffTools hooks. * - * @param array &$testModules The modules array to add to. - * @param ResourceLoader &$resourceLoader The resource loader. - * @return bool + * Insert a 'thank' link into revision interface, if the user is allowed to thank. + * + * @param RevisionRecord $revisionRecord RevisionRecord object to add the thank link for + * @param array &$links Links to add to the revision interface + * @param ?RevisionRecord $oldRevisionRecord RevisionRecord object of the "old" revision + * when viewing a diff + * @param UserIdentity $userIdentity The user performing the thanks. */ - public static function onResourceLoaderTestModules( array &$testModules, - ResourceLoader &$resourceLoader + public static function insertThankLink( + RevisionRecord $revisionRecord, + array &$links, + ?RevisionRecord $oldRevisionRecord, + UserIdentity $userIdentity ) { - if ( class_exists( 'SpecialMobileDiff' ) ) { - $testModules['qunit']['tests.ext.thanks.mobilediff'] = [ - 'localBasePath' => dirname( __DIR__ ), - 'remoteExtPath' => 'Thanks', - 'dependencies' => [ 'ext.thanks.mobilediff' ], - 'scripts' => [ - 'tests/qunit/test_ext.thanks.mobilediff.js', - ], - 'targets' => [ 'desktop', 'mobile' ], - ]; + $recipient = $revisionRecord->getUser(); + if ( $recipient === null ) { + // Cannot see the user + return; } - return true; - } - /** - * Handler for HistoryRevisionTools and DiffRevisionTools hooks. - * Inserts 'thank' link into revision interface - * @param Revision $rev Revision object to add the thank link for - * @param array &$links Links to add to the revision interface - * @param Revision|null $oldRev Revision object of the "old" revision when viewing a diff - * @param User $user The user performing the thanks. - * @return bool - */ - public static function insertThankLink( $rev, &$links, $oldRev, User $user ) { - $recipientId = $rev->getUser(); - $recipient = User::newFromId( $recipientId ); - $prev = $rev->getPrevious(); + $recipient = User::newFromIdentity( $recipient ); + $previous = MediaWikiServices::getInstance() + ->getRevisionLookup() + ->getPreviousRevision( $revisionRecord ); + + $user = User::newFromIdentity( $userIdentity ); + // Don't let users thank themselves. // Exclude anonymous users. // Exclude users who are blocked. @@ -56,16 +51,35 @@ class ThanksHooks { // (It supports discontinuous history created by Import or CX but // prevents thanking diff across multiple revisions) if ( !$user->isAnon() - && $recipientId !== $user->getId() - && !$user->isBlocked() + && !$user->equals( $recipient ) + && !self::isUserBlockedFromTitle( $user, $revisionRecord->getPageAsLinkTarget() ) && !$user->isBlockedGlobally() && self::canReceiveThanks( $recipient ) - && !$rev->isDeleted( Revision::DELETED_TEXT ) - && ( !$oldRev || !$prev || $prev->getId() === $oldRev->getId() ) + && !$revisionRecord->isDeleted( RevisionRecord::DELETED_TEXT ) + && ( !$oldRevisionRecord || !$previous || + $previous->getId() === $oldRevisionRecord->getId() ) ) { - $links[] = self::generateThankElement( $rev->getId(), $recipient ); + $links[] = self::generateThankElement( + $revisionRecord->getId(), + $user, + $recipient + ); } - return true; + } + + /** + * Check whether the user is blocked from the title associated with the revision. + * + * This queries the replicas for a block; if 'no block' is incorrectly reported, it + * will be caught by ApiThank::dieOnBlockedUser when the user attempts to thank. + * + * @param User $user + * @param LinkTarget $title + * @return bool + */ + private static function isUserBlockedFromTitle( User $user, LinkTarget $title ) { + return MediaWikiServices::getInstance()->getPermissionManager() + ->isBlockedFrom( $user, $title, true ); } /** @@ -77,7 +91,7 @@ class ThanksHooks { protected static function canReceiveThanks( User $user ) { global $wgThanksSendToBots; - if ( $user->isAnon() ) { + if ( $user->isAnon() || $user->isSystemUser() ) { return false; } @@ -92,28 +106,30 @@ class ThanksHooks { * Helper for self::insertThankLink * Creates either a thank link or thanked span based on users session * @param int $id Revision or log ID to generate the thank element for. + * @param User $sender User who sends thanks notification. * @param User $recipient User who receives thanks notification. * @param string $type Either 'revision' or 'log'. * @return string */ - protected static function generateThankElement( $id, $recipient, $type = 'revision' ) { - global $wgUser; + protected static function generateThankElement( + $id, User $sender, User $recipient, $type = 'revision' + ) { // Check if the user has already thanked for this revision or log entry. // Session keys are backwards-compatible, and are also used in the ApiCoreThank class. $sessionKey = ( $type === 'revision' ) ? $id : $type . $id; - if ( $wgUser->getRequest()->getSessionData( "thanks-thanked-$sessionKey" ) ) { + if ( $sender->getRequest()->getSessionData( "thanks-thanked-$sessionKey" ) ) { return Html::element( 'span', [ 'class' => 'mw-thanks-thanked' ], - wfMessage( 'thanks-thanked', $wgUser, $recipient->getName() )->text() + wfMessage( 'thanks-thanked', $sender->getName(), $recipient->getName() )->text() ); } $genderCache = MediaWikiServices::getInstance()->getGenderCache(); // Add 'thank' link $tooltip = wfMessage( 'thanks-thank-tooltip' ) - ->params( $wgUser->getName(), $recipient->getName() ) - ->text(); + ->params( $sender->getName(), $recipient->getName() ) + ->text(); $subpage = ( $type === 'revision' ) ? '' : 'Log/'; return Html::element( @@ -125,7 +141,7 @@ class ThanksHooks { 'data-' . $type . '-id' => $id, 'data-recipient-gender' => $genderCache->getGenderOf( $recipient->getName(), __METHOD__ ), ], - wfMessage( 'thanks-thank', $wgUser, $recipient->getName() )->text() + wfMessage( 'thanks-thank', $sender->getName(), $recipient->getName() )->text() ); } @@ -142,32 +158,26 @@ class ThanksHooks { /** * Handler for PageHistoryBeforeList hook. - * @see http://www.mediawiki.org/wiki/Manual:Hooks/PageHistoryBeforeList - * @param WikiPage|Article|ImagePage|CategoryPage|Page &$page The page for which the history - * is loading. + * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageHistoryBeforeList + * + * @param WikiPage|Article|ImagePage|CategoryPage $page Not used * @param RequestContext $context RequestContext object - * @return bool true in all cases */ - public static function onPageHistoryBeforeList( &$page, $context ) { + public static function onPageHistoryBeforeList( $page, $context ) { if ( $context->getUser()->isLoggedIn() ) { static::addThanksModule( $context->getOutput() ); } - return true; } /** - * Handler for DiffViewHeader hook. - * @see http://www.mediawiki.org/wiki/Manual:Hooks/DiffViewHeader + * Handler for DifferenceEngineViewHeader hook. + * @see https://www.mediawiki.org/wiki/Manual:Hooks/DifferenceEngineViewHeader * @param DifferenceEngine $diff DifferenceEngine object that's calling. - * @param Revision $oldRev Revision object of the "old" revision (may be null/invalid) - * @param Revision $newRev Revision object of the "new" revision - * @return bool true in all cases */ - public static function onDiffViewHeader( $diff, $oldRev, $newRev ) { + public static function onDifferenceEngineViewHeader( $diff ) { if ( $diff->getUser()->isLoggedIn() ) { static::addThanksModule( $diff->getOutput() ); } - return true; } /** @@ -176,7 +186,6 @@ class ThanksHooks { * @param array &$notifications array of Echo notifications * @param array &$notificationCategories array of Echo notification categories * @param array &$icons array of icon details - * @return bool */ public static function onBeforeCreateEchoEvent( &$notifications, &$notificationCategories, &$icons @@ -197,7 +206,7 @@ class ThanksHooks { ], ]; - if ( class_exists( Flow\FlowPresentationModel::class ) ) { + if ( ExtensionRegistry::getInstance()->isLoaded( 'Flow' ) ) { $notifications['flow-thank'] = [ 'category' => 'edit-thank', 'group' => 'positive', @@ -216,15 +225,12 @@ class ThanksHooks { 'rtl' => 'Thanks/userTalk-constructive-rtl.svg' ] ]; - - return true; } /** * Add user to be notified on echo event * @param EchoEvent $event The event. * @param User[] &$users The user list to add to. - * @return bool */ public static function onEchoGetDefaultNotifiedUsers( $event, &$users ) { switch ( $event->getType() ) { @@ -239,15 +245,13 @@ class ThanksHooks { $users[$recipientId] = $recipient; break; } - return true; } /** * Handler for LocalUserCreated hook - * @see http://www.mediawiki.org/wiki/Manual:Hooks/LocalUserCreated + * @see https://www.mediawiki.org/wiki/Manual:Hooks/LocalUserCreated * @param User $user User object that was created. * @param bool $autocreated True when account was auto-created - * @return bool */ public static function onAccountCreated( $user, $autocreated ) { // New users get echo preferences set that are not the default settings for existing users. @@ -256,15 +260,14 @@ class ThanksHooks { $user->setOption( 'echo-subscriptions-email-edit-thank', true ); $user->saveSettings(); } - return true; } /** * Add thanks button to SpecialMobileDiff page * @param OutputPage &$output OutputPage object * @param MobileContext $ctx MobileContext object - * @param array $revisions Array of the two revisions that are being compared in the diff - * @return bool true in all cases + * @param array $revisions Array with two elements, either nulls or RevisionRecord objects for + * the two revisions that are being compared in the diff */ public static function onBeforeSpecialMobileDiffDisplay( &$output, $ctx, $revisions ) { $rev = $revisions[1]; @@ -272,8 +275,9 @@ class ThanksHooks { // If the MobileFrontend extension is installed and the user is // logged in or recipient is not a bot if bots cannot receive thanks, show a 'Thank' link. if ( $rev - && class_exists( 'SpecialMobileDiff' ) - && self::canReceiveThanks( User::newFromId( $rev->getUser() ) ) + && ExtensionRegistry::getInstance()->isLoaded( 'MobileFrontend' ) + && $rev->getUser() + && self::canReceiveThanks( User::newFromIdentity( $rev->getUser() ) ) && $output->getUser()->isLoggedIn() ) { $output->addModules( [ 'ext.thanks.mobilediff' ] ); @@ -284,7 +288,6 @@ class ThanksHooks { } } - return true; } /** @@ -292,11 +295,9 @@ class ThanksHooks { * So users can just type in a username for target and it'll work. * @link https://www.mediawiki.org/wiki/Manual:Hooks/GetLogTypesOnUser * @param string[] &$types The list of log types, to add to. - * @return bool */ public static function onGetLogTypesOnUser( array &$types ) { $types[] = 'thanks'; - return true; } /** @@ -306,7 +307,6 @@ class ThanksHooks { * @link https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay * @param OutputPage $out OutputPage object * @param Skin $skin The skin in use. - * @return bool */ public static function onBeforePageDisplay( OutputPage $out, $skin ) { $title = $out->getTitle(); @@ -318,7 +318,6 @@ class ThanksHooks { if ( $title->isSpecial( 'Log' ) ) { static::addThanksModule( $out ); } - return true; } /** @@ -326,17 +325,15 @@ class ThanksHooks { * Flow is installed. * * @param ApiModuleManager $moduleManager Module manager instance - * @return bool */ public static function onApiMainModuleManager( ApiModuleManager $moduleManager ) { - if ( class_exists( 'FlowHooks' ) ) { + if ( ExtensionRegistry::getInstance()->isLoaded( 'Flow' ) ) { $moduleManager->addModule( 'flowthank', 'action', 'ApiFlowThank' ); } - return true; } /** @@ -344,7 +341,6 @@ class ThanksHooks { * * @param EchoEvent $event The event being notified. * @param string &$bundleString Determines how the notification should be bundled. - * @return bool True for success */ public static function onEchoGetBundleRules( $event, &$bundleString ) { switch ( $event->getType() ) { @@ -370,10 +366,11 @@ class ThanksHooks { } break; } - return true; } /** + * Insert a 'thank' link into the log interface, if the user is allowed to thank. + * * @link https://www.mediawiki.org/wiki/Manual:Hooks/LogEventsListLineEnding * @param LogEventsList $page The log events list. * @param string &$ret The lineending HTML, to modify. @@ -385,10 +382,15 @@ class ThanksHooks { public static function onLogEventsListLineEnding( LogEventsList $page, &$ret, DatabaseLogEntry $entry, &$classes, &$attribs ) { - global $wgUser; - - // Don't thank if anonymous or blocked - if ( $wgUser->isAnon() || $wgUser->isBlocked() || $wgUser->isBlockedGlobally() ) { + $user = $page->getUser(); + + // Don't thank if anonymous or blocked or if user is deleted from the log entry + if ( + $user->isAnon() + || $entry->isDeleted( LogPage::DELETED_USER ) + || self::isUserBlockedFromTitle( $user, $entry->getTarget() ) + || $user->isBlockedGlobally() + ) { return; } @@ -405,7 +407,7 @@ class ThanksHooks { // Don't check for deleted revision (this avoids extraneous queries from Special:Log). $recipient = $entry->getPerformer(); if ( !$recipient - || $recipient->getId() === $wgUser->getId() + || $recipient->getId() === $user->getId() || !self::canReceiveThanks( $recipient ) ) { return; @@ -414,8 +416,8 @@ class ThanksHooks { // Create thank link either for the revision (if there is an associated revision ID) // or the log entry. $type = $entry->getAssociatedRevId() ? 'revision' : 'log'; - $id = $entry->getAssociatedRevId() ? $entry->getAssociatedRevId() : $entry->getId(); - $thankLink = self::generateThankElement( $id, $recipient, $type ); + $id = $entry->getAssociatedRevId() ?: $entry->getId(); + $thankLink = self::generateThankElement( $id, $user, $recipient, $type ); // Add parentheses to match what's done with Thanks in revision lists and diff displays. $ret .= ' ' . wfMessage( 'parentheses' )->rawParams( $thankLink )->escaped(); |