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