Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
21.05% |
8 / 38 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
| Hooks | |
21.05% |
8 / 38 |
|
0.00% |
0 / 5 |
159.20 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| onGetPreferences | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| onPageSaveComplete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| maybeSendNotification | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
110 | |||
| isTwlEligible | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
2.01 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace MediaWiki\Extension\TheWikipediaLibrary; |
| 4 | |
| 5 | use MediaWiki\Config\Config; |
| 6 | use MediaWiki\Config\ConfigFactory; |
| 7 | use MediaWiki\Deferred\DeferredUpdates; |
| 8 | use MediaWiki\Extension\CentralAuth\User\CentralAuthUser; |
| 9 | use MediaWiki\Page\WikiPage; |
| 10 | use MediaWiki\Permissions\PermissionManager; |
| 11 | use MediaWiki\Preferences\Hook\GetPreferencesHook; |
| 12 | use MediaWiki\Registration\ExtensionRegistry; |
| 13 | use MediaWiki\Revision\RevisionRecord; |
| 14 | use MediaWiki\Storage\EditResult; |
| 15 | use MediaWiki\Storage\Hook\PageSaveCompleteHook; |
| 16 | use MediaWiki\Title\Title; |
| 17 | use MediaWiki\User\User; |
| 18 | use MediaWiki\User\UserFactory; |
| 19 | use MediaWiki\User\UserIdentity; |
| 20 | |
| 21 | /** |
| 22 | * TheWikipediaLibrary extension hooks |
| 23 | * |
| 24 | * @ingroup Extensions |
| 25 | * @license MIT |
| 26 | */ |
| 27 | class Hooks implements |
| 28 | PageSaveCompleteHook, |
| 29 | GetPreferencesHook |
| 30 | { |
| 31 | private readonly Config $config; |
| 32 | |
| 33 | public function __construct( |
| 34 | ConfigFactory $configFactory, |
| 35 | private readonly PermissionManager $permissionManager, |
| 36 | private readonly UserFactory $userFactory, |
| 37 | ) { |
| 38 | $this->config = $configFactory->makeConfig( 'TheWikipediaLibrary' ); |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Add API preference tracking whether the user has been notified already. |
| 43 | * @param User $user |
| 44 | * @param array &$preferences |
| 45 | */ |
| 46 | public function onGetPreferences( $user, &$preferences ) { |
| 47 | $preferences['twl-notified'] = [ |
| 48 | 'type' => 'api' |
| 49 | ]; |
| 50 | } |
| 51 | |
| 52 | /** |
| 53 | * Send a Wikipedia Library notification if the user has reached the required age and editcount. |
| 54 | * |
| 55 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageSaveComplete |
| 56 | * |
| 57 | * @note parameters include classes not available before 1.35, so for those typehints |
| 58 | * are not used. The variable name reflects the class |
| 59 | * |
| 60 | * @param WikiPage $wikiPage |
| 61 | * @param UserIdentity $userIdentity |
| 62 | * @param string $summary |
| 63 | * @param int $flags |
| 64 | * @param RevisionRecord $revisionRecord |
| 65 | * @param EditResult $editResult |
| 66 | */ |
| 67 | public function onPageSaveComplete( |
| 68 | $wikiPage, |
| 69 | $userIdentity, |
| 70 | $summary, |
| 71 | $flags, |
| 72 | $revisionRecord, |
| 73 | $editResult |
| 74 | ) { |
| 75 | if ( $this->config->get( 'TwlSendNotifications' ) && |
| 76 | ExtensionRegistry::getInstance()->isLoaded( 'Echo' ) |
| 77 | ) { |
| 78 | $title = $wikiPage->getTitle(); |
| 79 | $this->maybeSendNotification( $userIdentity, $title ); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Decide whether to notify the user based on central auth eligibility and global preference state |
| 85 | * |
| 86 | * @param UserIdentity $userIdentity |
| 87 | * @param Title $title |
| 88 | */ |
| 89 | private function maybeSendNotification( UserIdentity $userIdentity, Title $title ) { |
| 90 | // Wrap in a POSTSEND deferred update to avoid blocking the HTTP response |
| 91 | DeferredUpdates::addCallableUpdate( function () use ( $userIdentity, $title ) { |
| 92 | $user = $this->userFactory->newFromUserIdentity( $userIdentity ); |
| 93 | // Only proceed if we're dealing with an authenticated non-system account |
| 94 | if ( !$user->isNamed() || $user->isSystemUser() ) { |
| 95 | return; |
| 96 | } |
| 97 | // Only proceed if we're dealing with a non-bot account |
| 98 | if ( $this->permissionManager->userHasRight( $user, 'bot' ) ) { |
| 99 | return; |
| 100 | } |
| 101 | // Only proceed if we're dealing with an SUL account |
| 102 | $centralAuthUser = CentralAuthUser::getInstance( $user ); |
| 103 | if ( !$centralAuthUser->isAttached() ) { |
| 104 | return; |
| 105 | } |
| 106 | // Only proceed if we haven't already notified this user |
| 107 | $twlNotifiedPref = PreferenceHelper::getGlobalPreference( $user, 'twl-notified' ); |
| 108 | if ( $twlNotifiedPref === 'yes' ) { |
| 109 | return; |
| 110 | } |
| 111 | // Only proceed if we're dealing with an eligible account |
| 112 | if ( !$this->isTwlEligible( $centralAuthUser ) ) { |
| 113 | return; |
| 114 | } |
| 115 | // Set the twl-notified preference to 'no' if we haven't notified this user |
| 116 | // We've added this extra step to ensure that global preferences may be modified |
| 117 | // to avoid multiple notifications in case the preference isn't saved before the next edit |
| 118 | if ( $twlNotifiedPref === null ) { |
| 119 | PreferenceHelper::setGlobalPreference( $user, 'twl-notified', 'no' ); |
| 120 | return; |
| 121 | } |
| 122 | // Notify the user if: |
| 123 | // - they haven't been notified yet |
| 124 | // - we can successfully set the preference |
| 125 | if ( |
| 126 | $twlNotifiedPref === 'no' |
| 127 | && PreferenceHelper::setGlobalPreference( $user, 'twl-notified', 'yes' ) |
| 128 | ) { |
| 129 | EchoHelper::send( $user, $title ); |
| 130 | } |
| 131 | } ); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Determine Twl Eligibility |
| 136 | * |
| 137 | * @param CentralAuthUser $centralAuthUser |
| 138 | * @return bool |
| 139 | */ |
| 140 | public function isTwlEligible( CentralAuthUser $centralAuthUser ) { |
| 141 | $twlRegistrationDays = $this->config->get( 'TwlRegistrationDays' ); |
| 142 | $minimumAge = $twlRegistrationDays * 24 * 3600; |
| 143 | $accountAge = (int)wfTimestamp( TS_UNIX ) - |
| 144 | (int)wfTimestamp( TS_UNIX, $centralAuthUser->getRegistration() ); |
| 145 | if ( $accountAge < $minimumAge ) { |
| 146 | return false; |
| 147 | } |
| 148 | |
| 149 | $twlEditCount = $this->config->get( 'TwlEditCount' ); |
| 150 | $globalEditCount = $centralAuthUser->getGlobalEditCount(); |
| 151 | |
| 152 | return $globalEditCount >= $twlEditCount; |
| 153 | } |
| 154 | } |