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