Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 5
210
0.00% covered (danger)
0.00%
0 / 1
 getSurveyConfig
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 onBeforePageDisplay
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
90
 onResourceLoaderRegisterModules
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 onGetPreferences
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 formatDate
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Hooks for QuickSurveys extension
4 *
5 * @file
6 * @ingroup Extensions
7 */
8
9namespace QuickSurveys;
10
11use MediaWiki\Config\Config;
12use MediaWiki\MediaWikiServices;
13use MediaWiki\Output\Hook\BeforePageDisplayHook;
14use MediaWiki\Output\OutputPage;
15use MediaWiki\ResourceLoader as RL;
16use MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook;
17use MediaWiki\ResourceLoader\ResourceLoader;
18use MediaWiki\Session\SessionManager;
19use MediaWiki\User\User;
20use Skin;
21
22class Hooks implements
23    BeforePageDisplayHook,
24    ResourceLoaderRegisterModulesHook
25{
26
27    /**
28     * Get data about the enabled surveys to be exported to the ext.quicksurveys.lib module
29     * via a virtual file.
30     *
31     * @param RL\Context $context
32     * @param Config $conf
33     * @return array[]
34     */
35    public static function getSurveyConfig( RL\Context $context, Config $conf ) {
36        $surveys = MediaWikiServices::getInstance()->getService( 'QuickSurveys.EnabledSurveys' );
37
38        return array_map( static function ( Survey $survey ) {
39            return $survey->toArray();
40        }, $surveys );
41    }
42
43    /**
44     * Init QuickSurveys in BeforePageDisplay hook on existing pages in the main namespace
45     *
46     * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay
47     *
48     * @param OutputPage $out
49     * @param Skin $skin
50     */
51    public function onBeforePageDisplay( $out, $skin ): void {
52        $title = $out->getTitle();
53        $action = $out->getActionName();
54        $surveys = MediaWikiServices::getInstance()->getService( 'QuickSurveys.EnabledSurveys' );
55        $contextFilter = new SurveyContextFilter( $surveys );
56
57        if ( $contextFilter->isAnySurveyAvailable( $title, $action ) ) {
58            $needsFirstEdit = $contextFilter->isAudienceKeySet( 'firstEdit' );
59            $needsLastEdit = $contextFilter->isAudienceKeySet( 'lastEdit' );
60
61            // Only pass the user's first and last edit dates if a couple of
62            // conditions are met.
63            //
64            // First, there must be an available survey that requires one of
65            // these. Secondly, we should only query for them if the user has
66            // any edits in the first place. Fetching the total count is much
67            // faster than finding the timestamps of specific edits.
68            if ( $needsFirstEdit || $needsLastEdit ) {
69                $userEditTracker = MediaWikiServices::getInstance()->getUserEditTracker();
70                $user = SessionManager::getGlobalSession()->getUser();
71
72                if ( $userEditTracker->getUserEditCount( $user ) > 0 ) {
73                    if ( $needsFirstEdit ) {
74                        $firstEditTimestamp = $userEditTracker->getFirstEditTimestamp( $user );
75                        $out->addJsConfigVars( [
76                            'wgQSUserFirstEditDate' =>
77                                $firstEditTimestamp ? $this->formatDate( $firstEditTimestamp ) : null,
78                        ] );
79                    }
80
81                    if ( $needsLastEdit ) {
82                        $lastEditTimestamp = $userEditTracker->getLatestEditTimestamp( $user );
83                        $out->addJsConfigVars( [
84                            'wgQSUserLastEditDate' =>
85                                $lastEditTimestamp ? $this->formatDate( $lastEditTimestamp ) : null,
86                        ] );
87                    }
88                }
89            }
90
91            // TODO: It's annoying that we parse survey config a second time, inside this indirected
92            //  call.  Ideally we could construct the ResourceLoader data module right here.
93            $out->addModules( 'ext.quicksurveys.init' );
94        }
95    }
96
97    /**
98     * ResourceLoaderRegisterModules hook handler
99     *
100     * Registers needed modules for enabled surveys
101     *
102     * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderRegisterModules
103     *
104     * @param ResourceLoader $resourceLoader
105     */
106    public function onResourceLoaderRegisterModules( ResourceLoader $resourceLoader ): void {
107        $surveys = MediaWikiServices::getInstance()->getService( 'QuickSurveys.EnabledSurveys' );
108
109        foreach ( $surveys as $survey ) {
110            $moduleName = $survey->getResourceLoaderModuleName();
111            $module = [
112                $moduleName => [
113                    'dependencies' => [ 'ext.quicksurveys.lib.vue' ],
114                    'messages' => $survey->getMessages(),
115                ],
116            ];
117
118            $resourceLoader->register( $module );
119        }
120    }
121
122    /**
123     * Adds a default-enabled preference to gate the feature
124     *
125     * @see https://www.mediawiki.org/wiki/Manual:Hooks/GetPreferences
126     *
127     * @param User $user
128     * @param array &$prefs
129     */
130    public static function onGetPreferences( User $user, array &$prefs ): void {
131        $prefs['displayquicksurveys'] = [
132            'type' => 'select',
133            'section' => 'personal/quicksurveyext',
134            'label-message' => 'ext-quicksurveys-pref-displayquicksurveys-label',
135            'help-message' => 'ext-quicksurveys-pref-displayquicksurveys-help',
136            'options' => [
137                (string)wfMessage( 'ext-quicksurveys-pref-displayquicksurveys-option-enabled' ) => 1,
138                (string)wfMessage( 'ext-quicksurveys-pref-displayquicksurveys-option-disabled' ) => 0,
139            ],
140        ];
141    }
142
143    /**
144     * Convert a string timestamp with format (YYYYMMDDHHSS) to (YY-MM-DD)
145     *
146     * @param string $timestamp
147     */
148    private function formatDate( string $timestamp ): string {
149        $year = substr( $timestamp, 0, 4 );
150        $month = substr( $timestamp, 4, 2 );
151        $day = substr( $timestamp, 6, 2 );
152
153        return "{$year}-{$month}-{$day}";
154    }
155}