Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
18.18% covered (danger)
18.18%
6 / 33
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Decisions
18.18% covered (danger)
18.18%
6 / 33
20.00% covered (danger)
20.00%
1 / 5
138.23
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 shouldShowCookieWarning
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 isInConfiguredRegion
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 shouldAddResourceLoaderComponents
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getCountryCodeFromIP
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace CookieWarning;
4
5use Config;
6use ConfigException;
7use IContextSource;
8use MediaWiki\User\UserOptionsLookup;
9use MWException;
10use WANObjectCache;
11
12class Decisions {
13    private Config $config;
14    private GeoLocation $geoLocation;
15    private WANObjectCache $cache;
16    private UserOptionsLookup $userOptionsLookup;
17
18    private const CACHE_KEY = 'cookieWarningIpLookupCache:';
19
20    public function __construct(
21        Config $config,
22        GeoLocation $geoLocation,
23        WANObjectCache $cache,
24        UserOptionsLookup $userOptionsLookup
25    ) {
26        $this->config = $config;
27        $this->geoLocation = $geoLocation;
28        $this->cache = $cache;
29        $this->userOptionsLookup = $userOptionsLookup;
30    }
31
32    /**
33     * Checks, if the CookieWarning information bar should be visible to this user on
34     * this page.
35     *
36     * @param IContextSource $context
37     * @return bool Returns true, if the cookie warning should be visible, false otherwise.
38     * @throws ConfigException
39     * @throws MWException
40     */
41    public function shouldShowCookieWarning( IContextSource $context ) {
42        $user = $context->getUser();
43
44        return $this->config->get( 'CookieWarningEnabled' ) &&
45            !$this->userOptionsLookup->getBoolOption( $user, 'cookiewarning_dismissed' ) &&
46            !$context->getRequest()->getCookie( 'cookiewarning_dismissed' ) &&
47            ( $this->config->get( 'CookieWarningGeoIPLookup' ) === 'js' ||
48                $this->isInConfiguredRegion( $context ) );
49    }
50
51    /**
52     * Checks, if the user is in one of the configured regions.
53     *
54     * @param IContextSource $context
55     * @return bool
56     * @throws ConfigException
57     * @throws MWException
58     */
59    private function isInConfiguredRegion( IContextSource $context ) {
60        if ( !$this->config->get( 'CookieWarningForCountryCodes' ) ||
61            $this->config->get( 'CookieWarningGeoIPLookup' ) === 'none' ) {
62            wfDebugLog( 'CookieWarning', 'IP geolocation not configured, skipping.' );
63
64            return true;
65        }
66
67        $countryCode = $this->getCountryCodeFromIP( $context->getRequest()->getIP() );
68
69        return $countryCode === '' || array_key_exists( $countryCode,
70            $this->config->get( 'CookieWarningForCountryCodes' ) );
71    }
72
73    /**
74     * @return bool
75     * @throws ConfigException
76     */
77    public function shouldAddResourceLoaderComponents() {
78        return $this->config->get( 'CookieWarningGeoIPLookup' ) === 'js' &&
79            is_array( $this->config->get( 'CookieWarningForCountryCodes' ) );
80    }
81
82    /**
83     * @param string $currentIP
84     * @return string The country code associated with the IP or empty string if not able to locate.
85     * @throws ConfigException
86     */
87    private function getCountryCodeFromIP( $currentIP ) {
88        $cacheKey = $this->cache->makeGlobalKey( __CLASS__, self::CACHE_KEY . $currentIP );
89        $lookedUpCountryCode = $this->cache->get( $cacheKey );
90
91        if ( is_string( $lookedUpCountryCode ) ) {
92            return $lookedUpCountryCode;
93        }
94
95        wfDebugLog( 'CookieWarning', 'Try to locate the user\'s IP address.' );
96        $location = $this->geoLocation->locate( $currentIP );
97        if ( $location === null ) {
98            wfDebugLog( 'CookieWarning',
99                'Locating the user\'s IP address failed or is misconfigured.' );
100
101            return '';
102        }
103
104        $this->cache->set( $cacheKey, $location );
105
106        wfDebugLog( 'CookieWarning',
107            'Locating the user was successful, located region: ' . $location );
108
109        return $location;
110    }
111}