Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
21.43% covered (danger)
21.43%
9 / 42
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
21.43% covered (danger)
21.43%
9 / 42
0.00% covered (danger)
0.00%
0 / 4
157.18
0.00% covered (danger)
0.00%
0 / 1
 onGetPreferences
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 onPageSaveComplete
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 maybeSendNotification
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
132
 isTwlEligible
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
2.00
1<?php
2
3namespace MediaWiki\Extension\TheWikipediaLibrary;
4
5use ExtensionRegistry;
6use MediaWiki\Deferred\DeferredUpdates;
7use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
8use MediaWiki\MediaWikiServices;
9use MediaWiki\Preferences\Hook\GetPreferencesHook;
10use MediaWiki\Revision\RevisionRecord;
11use MediaWiki\Storage\EditResult;
12use MediaWiki\Storage\Hook\PageSaveCompleteHook;
13use MediaWiki\Title\Title;
14use MediaWiki\User\User;
15use MediaWiki\User\UserIdentity;
16use WikiPage;
17
18/**
19 * TheWikipediaLibrary extension hooks
20 *
21 * @file
22 * @ingroup Extensions
23 * @license MIT
24 */
25class 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}