Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.33% covered (warning)
73.33%
11 / 15
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
WikimediaEventsCountryCodeLookup
73.33% covered (warning)
73.33%
11 / 15
50.00% covered (danger)
50.00%
2 / 4
11.90
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCountryCodeFormattedForEvent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFromCookie
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getFromGeoIP
62.50% covered (warning)
62.50%
5 / 8
0.00% covered (danger)
0.00%
0 / 1
7.90
1<?php
2
3namespace WikimediaEvents;
4
5use GeoIp2\Database\Reader;
6use GeoIp2\Exception\AddressNotFoundException;
7use MaxMind\Db\Reader\InvalidDatabaseException;
8use MediaWiki\Logger\LoggerFactory;
9use MediaWiki\Request\WebRequest;
10use Wikimedia\IPUtils;
11
12/**
13 * Lookup ISO 3166-1 alpha code for a country for an IP address, using cookie or GeoIP2
14 */
15class WikimediaEventsCountryCodeLookup {
16
17    private ?Reader $reader;
18
19    /**
20     * @param Reader|null $reader
21     */
22    public function __construct( ?Reader $reader ) {
23        $this->reader = $reader;
24    }
25
26    public static function getCountryCodeFormattedForEvent( ?string $countryCode ): string {
27        return $countryCode ?? 'Unknown';
28    }
29
30    /**
31     * @param WebRequest $webRequest
32     * @return string|null
33     */
34    public static function getFromCookie( WebRequest $webRequest ): ?string {
35        $geoIpCookie = $webRequest->getCookie( 'GeoIP', '' );
36        // Use the GeoIP cookie if available.
37        if ( $geoIpCookie ) {
38            $components = explode( ':', $geoIpCookie );
39            return $components[0];
40        }
41        return null;
42    }
43
44    /**
45     * Attempt to obtain the country code for an IP address using GeoIP library.
46     *
47     * @param WebRequest $webRequest
48     * @return null|string
49     *   The two-character ISO 3166-1 alpha code for the country, or null if not found
50     */
51    public function getFromGeoIP( WebRequest $webRequest ): ?string {
52        $country = null;
53        $ip = $webRequest->getIP();
54
55        if ( $this->reader && IPUtils::isValid( $ip ) ) {
56            try {
57                $country = $this->reader->country( $ip )->country->isoCode;
58            } catch ( InvalidDatabaseException $e ) {
59                // Note, the method above can throw an exception even if instantiating
60                // the reader with the database does not. See ::getRecord in Reader
61                LoggerFactory::getInstance( 'WikimediaEvents' )->error( $e->getMessage() );
62            } catch ( AddressNotFoundException $e ) {
63                // Ignore cases where the IP isn't found.
64            }
65        }
66        return $country ?: null;
67    }
68
69}