Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
61.18% covered (warning)
61.18%
52 / 85
50.00% covered (danger)
50.00%
4 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
61.18% covered (warning)
61.18%
52 / 85
50.00% covered (danger)
50.00%
4 / 8
46.81
0.00% covered (danger)
0.00%
0 / 1
 onBeforeInitialize
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 onSkinAfterContent
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 generateElements
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
1 / 1
2
 getMoreLink
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
6
 onBeforePageDisplay
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 onResourceLoaderGetConfigVars
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 getConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 onGetPreferences
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace CookieWarning;
4
5use Config;
6use ConfigException;
7use Html;
8use MediaWiki;
9use MediaWiki\Hook\BeforeInitializeHook;
10use MediaWiki\Hook\BeforePageDisplayHook;
11use MediaWiki\Hook\SkinAfterContentHook;
12use MediaWiki\MediaWikiServices;
13use MediaWiki\Preferences\Hook\GetPreferencesHook;
14use MediaWiki\ResourceLoader\Hook\ResourceLoaderGetConfigVarsHook;
15use MWException;
16use OOUI\ButtonInputWidget;
17use OOUI\ButtonWidget;
18use OOUI\HorizontalLayout;
19use OutputPage;
20use Skin;
21use Title;
22use User;
23use WebRequest;
24
25class Hooks implements
26    SkinAfterContentHook,
27    GetPreferencesHook,
28    BeforeInitializeHook,
29    BeforePageDisplayHook,
30    ResourceLoaderGetConfigVarsHook
31{
32    /**
33     * BeforeInitialize hook handler.
34     *
35     * If the disablecookiewarning POST data is send, disables the cookiewarning bar with a
36     * cookie or a user preference, if the user is logged in.
37     *
38     * @param Title $title
39     * @param null $unused
40     * @param OutputPage $output
41     * @param User $user
42     * @param WebRequest $request
43     * @param MediaWiki $mediawiki
44     * @throws MWException
45     */
46    public function onBeforeInitialize( $title, $unused, $output, $user, $request, $mediawiki ) {
47        if ( !$request->wasPosted() || !$request->getVal( 'disablecookiewarning' ) ) {
48            return;
49        }
50
51        if ( $user->isRegistered() ) {
52            $userOptionsManager = MediaWikiServices::getInstance()->getUserOptionsManager();
53            $userOptionsManager->setOption( $user, 'cookiewarning_dismissed', 1 );
54            $userOptionsManager->saveOptions( $user );
55        } else {
56            $request->response()->setCookie( 'cookiewarning_dismissed', true );
57        }
58        $output->redirect( $request->getRequestURL() );
59    }
60
61    /**
62     * SkinAfterContent hook handler.
63     *
64     * Adds the CookieWarning information bar to the output html.
65     *
66     * @param string &$data
67     * @param Skin $skin
68     *
69     * @throws MWException
70     */
71    public function onSkinAfterContent( &$data, $skin ) {
72        /** @var Decisions $cookieWarningDecisions */
73        $cookieWarningDecisions = MediaWikiServices::getInstance()
74            ->getService( 'CookieWarning.Decisions' );
75
76        if ( !$cookieWarningDecisions->shouldShowCookieWarning( $skin->getContext() ) ) {
77            return;
78        }
79
80        $data .= self::generateElements( $skin );
81    }
82
83    /**
84     * Generates the elements for the banner.
85     *
86     * @param Skin $skin
87     * @return string|null The html for cookie notice.
88     */
89    private static function generateElements( Skin $skin ): ?string {
90        $moreLink = self::getMoreLink();
91
92        $buttons = [];
93        if ( $moreLink ) {
94            $buttons[] = new ButtonWidget( [
95                'href' => $moreLink,
96                'label' => $skin->msg( 'cookiewarning-moreinfo-label' )->text(),
97                'flags' => [ 'progressive' ]
98            ] );
99        }
100        $buttons[] = new ButtonInputWidget( [
101            'type' => 'submit',
102            'label' => $skin->msg( 'cookiewarning-ok-label' )->text(),
103            'name' => 'disablecookiewarning',
104            'value' => 'OK',
105            'flags' => [ 'primary', 'progressive' ]
106        ] );
107
108        $form = Html::rawElement(
109            'form',
110            [ 'method' => 'POST' ],
111            new HorizontalLayout( [ 'items' => $buttons ] )
112        );
113
114        return Html::openElement(
115                'div',
116                [ 'class' => 'mw-cookiewarning-container' ]
117            ) .
118            Html::openElement(
119                'div',
120                [ 'class' => 'mw-cookiewarning-text' ]
121            ) .
122            Html::element(
123                'span',
124                [],
125                $skin->msg( 'cookiewarning-info' )->text()
126            ) .
127            Html::closeElement( 'div' ) .
128            $form .
129            Html::closeElement( 'div' );
130    }
131
132    /**
133     * Returns the target for the "More information" link of the cookie warning bar, if one is set.
134     * The link can be set by either (checked in this order):
135     *  - the configuration variable $wgCookieWarningMoreUrl
136     *  - the interface message MediaWiki:Cookiewarning-more-link
137     *  - the interface message MediaWiki:Cookie-policy-link (bc T145781)
138     *
139     * @return string|null The url or null if none set
140     * @throws ConfigException
141     */
142    private static function getMoreLink(): ?string {
143        $conf = self::getConfig();
144        if ( $conf->get( 'CookieWarningMoreUrl' ) ) {
145            return $conf->get( 'CookieWarningMoreUrl' );
146        }
147
148        $cookieWarningMessage = wfMessage( 'cookiewarning-more-link' );
149        if ( $cookieWarningMessage->exists() && !$cookieWarningMessage->isDisabled() ) {
150            return $cookieWarningMessage->text();
151        }
152
153        $cookiePolicyMessage = wfMessage( 'cookie-policy-link' );
154        if ( $cookiePolicyMessage->exists() && !$cookiePolicyMessage->isDisabled() ) {
155            return $cookiePolicyMessage->text();
156        }
157
158        return null;
159    }
160
161    /**
162     * BeforePageDisplay hook handler.
163     *
164     * Adds the required style and JS module, if cookiewarning is enabled.
165     *
166     * @param OutputPage $out
167     * @param Skin $skin
168     * @throws ConfigException
169     * @throws MWException
170     */
171    public function onBeforePageDisplay( $out, $skin ): void {
172        /** @var Decisions $cookieWarningDecisions */
173        $cookieWarningDecisions = MediaWikiServices::getInstance()
174            ->getService( 'CookieWarning.Decisions' );
175
176        if ( !$cookieWarningDecisions->shouldShowCookieWarning( $out->getContext() ) ) {
177            return;
178        }
179
180        $modules = [ 'ext.CookieWarning' ];
181        $moduleStyles = [ 'ext.CookieWarning.styles' ];
182
183        if ( $cookieWarningDecisions->shouldAddResourceLoaderComponents() ) {
184            $modules[] = 'ext.CookieWarning.geolocation';
185            $moduleStyles[] = 'ext.CookieWarning.geolocation.styles';
186        }
187        $out->addModules( $modules );
188        $out->addModuleStyles( $moduleStyles );
189        $out->enableOOUI();
190    }
191
192    /**
193     * ResourceLoaderGetConfigVars hook handler.
194     *
195     * @param array &$vars
196     * @param string $skin
197     * @param Config $config
198     *
199     * @throws ConfigException
200     */
201    public function onResourceLoaderGetConfigVars( array &$vars, $skin, Config $config ): void {
202        /** @var Decisions $cookieWarningDecisions */
203        $cookieWarningDecisions = MediaWikiServices::getInstance()
204            ->getService( 'CookieWarning.Decisions' );
205        $conf = self::getConfig();
206
207        if ( $cookieWarningDecisions->shouldAddResourceLoaderComponents() ) {
208            $vars += [
209                'wgCookieWarningGeoIPServiceURL' => $conf->get( 'CookieWarningGeoIPServiceURL' ),
210                'wgCookieWarningForCountryCodes' => $conf->get( 'CookieWarningForCountryCodes' ),
211            ];
212        }
213    }
214
215    /**
216     * Returns the Config object for the CookieWarning extension.
217     *
218     * @return Config
219     */
220    private static function getConfig(): Config {
221        return MediaWikiServices::getInstance()->getService( 'CookieWarning.Config' );
222    }
223
224    /**
225     * GetPreferences hook handler
226     *
227     * @see https://www.mediawiki.org/wiki/Manual:Hooks/GetPreferences
228     *
229     * @param User $user
230     * @param array &$defaultPreferences
231     * @return bool
232     */
233    public function onGetPreferences( $user, &$defaultPreferences ): bool {
234        $defaultPreferences['cookiewarning_dismissed'] = [
235            'type' => 'api',
236            'default' => '0',
237        ];
238        return true;
239    }
240}