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