MDL-86348 libraries: Upgrade GeoIP2 and Maxmind DB Reader

- GeoIP2 PHP API 3.2.0
- MaxMind DB Reader API 1.12.1
This commit is contained in:
yusufwib01
2025-08-22 00:44:18 +07:00
parent c1311feeb1
commit 42b8deeb63
15 changed files with 199 additions and 65 deletions
+10 -1
View File
@@ -1,6 +1,15 @@
CHANGELOG
=========
3.2.0 (2025-05-05)
------------------
* Support for the GeoIP Anonymous Plus database has been added. To do a
lookup in this database, use the `anonymousPlus` method on
`GeoIP2\Database\Reader`.
* `metroCode` on `GeoIp2\Record\Location` has been deprecated. The code
values are no longer being maintained.
3.1.0 (2024-11-15)
------------------
@@ -15,7 +24,7 @@ CHANGELOG
* IMPORTANT: PHP 8.1 or greater is now required.
* BREAKING: Read-only properties are now used for the model and record
classes rather than magic methods. This significantly improves performance.
* BREAKING: The `raw` property on model classess and the `record` property on
* BREAKING: The `raw` property on model classes and the `record` property on
record classes have been removed.
* BREAKING: On `GeoIp2\Record\Traits`, the deprecated `isAnonymousProxy` and
`isSatelliteProvider` properties have been removed.
+23 -1
View File
@@ -162,6 +162,28 @@ print($record->network . "\n"); // '128.101.101.101/32'
```
### Anonymous Plus Example ###
```php
<?php
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;
// This creates the Reader object, which should be reused across
// lookups.
$anonymousDbReader = new Reader('/usr/local/share/GeoIP/GeoIP-Anonymous-Plus.mmdb');
$record = $anonymousDbReader->anonymousIp('203.0.113.0');
print($record->anonymizerConfidence . "\n"); // 30
print($record->networkLastSeen . "\n"); // '2025-04-14'
print($record->providerName . "\n"); // 'FooBar VPN'
print($record->ipAddress . "\n"); // '203.0.113.0'
print($record->network . "\n"); // '203.0.113.0/32'
```
### Connection-Type Example ###
```php
@@ -443,6 +465,6 @@ The GeoIP2 PHP API uses [Semantic Versioning](https://semver.org/).
## Copyright and License ##
This software is Copyright (c) 2013-2024 by MaxMind, Inc.
This software is Copyright (c) 2013-2025 by MaxMind, Inc.
This is free software, licensed under the Apache License, Version 2.0.
+1 -1
View File
@@ -13,7 +13,7 @@
}
],
"require": {
"maxmind-db/reader": "^1.12.0",
"maxmind-db/reader": "^1.12.1",
"maxmind/web-service-common": "~0.10",
"php": ">=8.1",
"ext-json": "*"
@@ -6,6 +6,7 @@ namespace GeoIp2\Database;
use GeoIp2\Exception\AddressNotFoundException;
use GeoIp2\Model\AnonymousIp;
use GeoIp2\Model\AnonymousPlus;
use GeoIp2\Model\Asn;
use GeoIp2\Model\City;
use GeoIp2\Model\ConnectionType;
@@ -44,14 +45,8 @@ use MaxMind\Db\Reader\Metadata;
*/
class Reader implements ProviderInterface
{
private DbReader $dbReader;
private string $dbType;
/**
* @var array<string>
*/
private array $locales;
private readonly DbReader $dbReader;
private readonly string $dbType;
/**
* Constructor.
@@ -64,11 +59,11 @@ class Reader implements ProviderInterface
*/
public function __construct(
string $filename,
array $locales = ['en']
/** @var array<string> */
public readonly array $locales = ['en']
) {
$this->dbReader = new DbReader($filename);
$this->dbType = $this->dbReader->metadata()->databaseType;
$this->locales = $locales;
}
/**
@@ -78,6 +73,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function city(string $ipAddress): City
{
@@ -91,6 +87,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function country(string $ipAddress): Country
{
@@ -104,6 +101,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function anonymousIp(string $ipAddress): AnonymousIp
{
@@ -114,6 +112,24 @@ class Reader implements ProviderInterface
);
}
/**
* This method returns a GeoIP Anonymous Plus model.
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function anonymousPlus(string $ipAddress): AnonymousPlus
{
return $this->flatModelFor(
AnonymousPlus::class,
'GeoIP-Anonymous-Plus',
$ipAddress
);
}
/**
* This method returns a GeoLite2 ASN model.
*
@@ -121,6 +137,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function asn(string $ipAddress): Asn
{
@@ -138,6 +155,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function connectionType(string $ipAddress): ConnectionType
{
@@ -155,6 +173,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function domain(string $ipAddress): Domain
{
@@ -172,6 +191,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function enterprise(string $ipAddress): Enterprise
{
@@ -185,6 +205,7 @@ class Reader implements ProviderInterface
*
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
* @throws \BadMethodCallException if this database type is not supported
*/
public function isp(string $ipAddress): Isp
{
@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace GeoIp2\Model;
/**
* This class provides the GeoIP Anonymous Plus model.
*/
class AnonymousPlus extends AnonymousIp
{
/**
* @var int|null a score ranging from 1 to 99 that is our percent
* confidence that the network is currently part of
* an actively used VPN service
*/
public readonly ?int $anonymizerConfidence;
/**
* @var string|null The last day that the network was sighted in our
* analysis of anonymized networks. This is in the ISO
* 8601 date format, e.g., "2025-04-21".
*/
public readonly ?string $networkLastSeen;
/**
* @var string|null The name of the VPN provider (e.g., NordVPN,
* SurfShark, etc.) associated with the network.
*/
public readonly ?string $providerName;
/**
* @ignore
*
* @param array<string, mixed> $raw
*/
public function __construct(array $raw)
{
parent::__construct($raw);
$this->anonymizerConfidence = $raw['anonymizer_confidence'] ?? null;
$this->networkLastSeen = $raw['network_last_seen'] ?? null;
$this->providerName = $raw['provider_name'] ?? null;
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = parent::jsonSerialize();
if ($this->anonymizerConfidence !== null) {
$js['anonymizer_confidence'] = $this->anonymizerConfidence;
}
if ($this->networkLastSeen !== null) {
$js['network_last_seen'] = $this->networkLastSeen;
}
if ($this->providerName !== null) {
$js['provider_name'] = $this->providerName;
}
return $js;
}
}
+2 -2
View File
@@ -45,8 +45,8 @@ class Asn implements \JsonSerializable
public function __construct(array $raw)
{
$this->autonomousSystemNumber = $raw['autonomous_system_number'] ?? null;
$this->autonomousSystemOrganization =
$raw['autonomous_system_organization'] ?? null;
$this->autonomousSystemOrganization
= $raw['autonomous_system_organization'] ?? null;
$ipAddress = $raw['ip_address'];
$this->ipAddress = $ipAddress;
$this->network = Util::cidr($ipAddress, $raw['prefix_len']);
+20 -20
View File
@@ -43,18 +43,18 @@ class City extends Country
public readonly Postal $postal;
/**
* @var array<\GeoIp2\Record\Subdivision> An array of \GeoIp2\Record\Subdivision
* objects representing the country
* subdivisions for the requested IP
* address. The number and type of
* subdivisions varies by country,
* but a subdivision is typically a
* state, province, county, etc.
* Subdivisions are ordered from most
* general (largest) to most specific
* (smallest). If the response did
* not contain any subdivisions, this
* method returns an empty array.
* @var array<Subdivision> An array of \GeoIp2\Record\Subdivision
* objects representing the country
* subdivisions for the requested IP
* address. The number and type of
* subdivisions varies by country,
* but a subdivision is typically a
* state, province, county, etc.
* Subdivisions are ordered from most
* general (largest) to most specific
* (smallest). If the response did
* not contain any subdivisions, this
* method returns an empty array.
*/
public readonly array $subdivisions;
@@ -74,22 +74,22 @@ class City extends Country
if (!isset($raw['subdivisions'])) {
$this->subdivisions = [];
$this->mostSpecificSubdivision =
new Subdivision([], $locales);
$this->mostSpecificSubdivision
= new Subdivision([], $locales);
return;
}
$subdivisions = [];
foreach ($raw['subdivisions'] as $sub) {
$subdivisions[] =
new Subdivision($sub, $locales)
$subdivisions[]
= new Subdivision($sub, $locales)
;
}
// Not using end as we don't want to modify internal pointer.
$this->mostSpecificSubdivision =
$subdivisions[\count($subdivisions) - 1];
$this->mostSpecificSubdivision
= $subdivisions[\count($subdivisions) - 1];
$this->subdivisions = $subdivisions;
}
@@ -110,8 +110,8 @@ class City extends Country
$js['location'] = $location;
}
$postal =
$this->postal->jsonSerialize();
$postal
= $this->postal->jsonSerialize();
if (!empty($postal)) {
$js['postal'] = $postal;
}
+2 -2
View File
@@ -71,8 +71,8 @@ class Isp implements \JsonSerializable
public function __construct(array $raw)
{
$this->autonomousSystemNumber = $raw['autonomous_system_number'] ?? null;
$this->autonomousSystemOrganization =
$raw['autonomous_system_organization'] ?? null;
$this->autonomousSystemOrganization
= $raw['autonomous_system_organization'] ?? null;
$this->isp = $raw['isp'] ?? null;
$this->mobileCountryCode = $raw['mobile_country_code'] ?? null;
$this->mobileNetworkCode = $raw['mobile_network_code'] ?? null;
@@ -43,10 +43,10 @@ class Location implements \JsonSerializable
public readonly ?float $longitude;
/**
* @var int|null The metro code of the location if the location
* is in the US. MaxMind returns the same metro codes as the
* Google AdWords API. See
* https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions.
* @var int|null the metro code is a no-longer-maintained code for targeting
* advertisements in Google
*
* @deprecated
*/
public readonly ?int $metroCode;
@@ -51,14 +51,10 @@ use MaxMind\WebService\Client as WsClient;
*/
class Client implements ProviderInterface
{
/**
* @var array<string>
*/
private array $locales;
private WsClient $client;
private readonly WsClient $client;
private static string $basePath = '/geoip/v2.1';
public const VERSION = 'v3.1.0';
public const VERSION = 'v3.2.0';
/**
* Constructor.
@@ -86,11 +82,10 @@ class Client implements ProviderInterface
public function __construct(
int $accountId,
string $licenseKey,
array $locales = ['en'],
/** @var list<string> */
public readonly array $locales = ['en'], // Promoted and readonly
array $options = []
) {
$this->locales = $locales;
// This is for backwards compatibility. Do not remove except for a
// major version bump.
// @phpstan-ignore-next-line
@@ -98,9 +93,7 @@ class Client implements ProviderInterface
$options = ['host' => $options];
}
if (!isset($options['host'])) {
$options['host'] = 'geoip.maxmind.com';
}
$options['host'] ??= 'geoip.maxmind.com';
$options['userAgent'] = $this->userAgent();
@@ -139,7 +132,6 @@ class Client implements ProviderInterface
*/
public function city(string $ipAddress = 'me'): City
{
// @phpstan-ignore-next-line
return $this->responseFor('city', City::class, $ipAddress);
}
@@ -201,11 +193,29 @@ class Client implements ProviderInterface
*/
public function insights(string $ipAddress = 'me'): Insights
{
// @phpstan-ignore-next-line
return $this->responseFor('insights', Insights::class, $ipAddress);
}
private function responseFor(string $endpoint, string $class, string $ipAddress): Country
/**
* Generic helper method to call an endpoint and return the corresponding model.
*
* @template TModel of City|Country|Insights
*
* @param 'city'|'country'|'insights' $endpoint the endpoint name
* @param class-string<TModel> $class The specific model class string (e.g., City::class)
* @param string $ipAddress the IP address or 'me'
*
* @throws AddressNotFoundException
* @throws AuthenticationException
* @throws OutOfQueriesException
* @throws InvalidRequestException
* @throws HttpException
* @throws GeoIp2Exception
* @throws \InvalidArgumentException
*
* @return TModel the corresponding model object, matching the passed class string
*/
private function responseFor(string $endpoint, string $class, string $ipAddress): City|Country|Insights
{
if ($ipAddress !== 'me' && !filter_var($ipAddress, \FILTER_VALIDATE_IP)) {
throw new \InvalidArgumentException(
+6
View File
@@ -1,6 +1,12 @@
CHANGELOG
=========
1.12.1 (2025-05-05)
-------------------
* The C extension now checks that the database metadata lookup was
successful.
1.12.0 (2024-11-14)
-------------------
+1 -1
View File
@@ -180,6 +180,6 @@ The MaxMind DB Reader PHP API uses [Semantic Versioning](https://semver.org/).
## Copyright and License ##
This software is Copyright (c) 2014-2024 by MaxMind, Inc.
This software is Copyright (c) 2014-2025 by MaxMind, Inc.
This is free software, licensed under the Apache License, Version 2.0.
@@ -356,8 +356,8 @@ class Reader
}
throw new InvalidDatabaseException(
"Error opening database file ($filename). " .
'Is this a valid MaxMind DB file?'
"Error opening database file ($filename). "
. 'Is this a valid MaxMind DB file?'
);
}
@@ -106,10 +106,10 @@ class Metadata
);
}
$this->binaryFormatMajorVersion =
$metadata['binary_format_major_version'];
$this->binaryFormatMinorVersion =
$metadata['binary_format_minor_version'];
$this->binaryFormatMajorVersion
= $metadata['binary_format_major_version'];
$this->binaryFormatMinorVersion
= $metadata['binary_format_minor_version'];
$this->buildEpoch = $metadata['build_epoch'];
$this->databaseType = $metadata['database_type'];
$this->languages = $metadata['languages'];
+2 -2
View File
@@ -416,7 +416,7 @@ All rights reserved.</copyright>
<location>maxmind/GeoIp2</location>
<name>GeoIP2 PHP API</name>
<description>Library for processing of GeoIP data files.</description>
<version>3.1.0</version>
<version>3.2.0</version>
<license>Apache</license>
<licenseversion>2.0</licenseversion>
<repository>https://github.com/maxmind/GeoIP2-php</repository>
@@ -428,7 +428,7 @@ All rights reserved.</copyright>
<location>maxmind/MaxMind</location>
<name>MaxMind DB Reader API</name>
<description>PHP API for reading MaxMind DB files.</description>
<version>1.12.0</version>
<version>1.12.1</version>
<license>Apache</license>
<licenseversion>2.0</licenseversion>
<repository>https://github.com/maxmind/MaxMind-DB-Reader-php/</repository>