MDL-84162 libraries: Upgrade GeoIP2 and Maxmind DB Reader

- GeoIP2 PHP API 3.1.0
- MaxMind DB Reader API 1.12.0
This commit is contained in:
meirzamoodle
2025-03-04 13:08:17 +07:00
parent 688478cfa4
commit 10ee4503cf
33 changed files with 349 additions and 224 deletions
@@ -1,6 +1,14 @@
CHANGELOG
=========
3.1.0 (2024-11-15)
------------------
* This library no longer uses implicitly nullable parameter types. This
will fix deprecation warning in PHP 8.4. Reported by Steven Lewis.
GitHub #230.
* The PHPDoc type hints have been improved for use with PHPStan.
3.0.0 (2023-12-04)
------------------
@@ -266,11 +266,6 @@ You can keep your databases up to date with our
[Learn more about GeoIP Update on our developer
portal.](https://dev.maxmind.com/geoip/updating-databases?lang=en)
There is also a third-party tool for updating databases using PHP and
Composer. MaxMind does not offer support for this tool or maintain it.
[Learn more about the Geoip2 Update tool for PHP and Composer on its
GitHub page.](https://github.com/tronovav/geoip2-update)
## Web Service Client ##
### Usage ###
@@ -448,6 +443,6 @@ The GeoIP2 PHP API uses [Semantic Versioning](https://semver.org/).
## Copyright and License ##
This software is Copyright (c) 2013-2023 by MaxMind, Inc.
This software is Copyright (c) 2013-2024 by MaxMind, Inc.
This is free software, licensed under the Apache License, Version 2.0.
+2 -2
View File
@@ -13,8 +13,8 @@
}
],
"require": {
"maxmind-db/reader": "^1.11.1",
"maxmind/web-service-common": "~0.8",
"maxmind-db/reader": "^1.12.0",
"maxmind/web-service-common": "~0.10",
"php": ">=8.1",
"ext-json": "*"
},
+26 -39
View File
@@ -16,6 +16,7 @@ use GeoIp2\Model\Isp;
use GeoIp2\ProviderInterface;
use MaxMind\Db\Reader as DbReader;
use MaxMind\Db\Reader\InvalidDatabaseException;
use MaxMind\Db\Reader\Metadata;
/**
* Instances of this class provide a reader for the GeoIP2 database format.
@@ -55,12 +56,11 @@ class Reader implements ProviderInterface
/**
* Constructor.
*
* @param string $filename the path to the GeoIP2 database file
* @param array $locales list of locale codes to use in name property
* from most preferred to least preferred
* @param string $filename the path to the GeoIP2 database file
* @param array<string> $locales list of locale codes to use in name property
* from most preferred to least preferred
*
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function __construct(
string $filename,
@@ -76,10 +76,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function city(string $ipAddress): City
{
@@ -91,10 +89,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function country(string $ipAddress): Country
{
@@ -106,10 +102,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function anonymousIp(string $ipAddress): AnonymousIp
{
@@ -125,10 +119,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function asn(string $ipAddress): Asn
{
@@ -144,10 +136,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function connectionType(string $ipAddress): ConnectionType
{
@@ -163,10 +153,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function domain(string $ipAddress): Domain
{
@@ -182,10 +170,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function enterprise(string $ipAddress): Enterprise
{
@@ -197,10 +183,8 @@ class Reader implements ProviderInterface
*
* @param string $ipAddress an IPv4 or IPv6 address as a string
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address is
* not in the database
* @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
* is corrupt or invalid
* @throws AddressNotFoundException if the address is not in the database
* @throws InvalidDatabaseException if the database is corrupt or invalid
*/
public function isp(string $ipAddress): Isp
{
@@ -231,6 +215,9 @@ class Reader implements ProviderInterface
return new $class($record);
}
/**
* @return array{0:array<string, mixed>, 1:int}
*/
private function getRecord(string $class, string $type, string $ipAddress): array
{
if (!str_contains($this->dbType, $type)) {
@@ -267,9 +254,9 @@ class Reader implements ProviderInterface
* @throws \InvalidArgumentException if arguments are passed to the method
* @throws \BadMethodCallException if the database has been closed
*
* @return \MaxMind\Db\Reader\Metadata object for the database
* @return Metadata object for the database
*/
public function metadata(): DbReader\Metadata
public function metadata(): Metadata
{
return $this->dbReader->metadata();
}
@@ -18,7 +18,7 @@ class HttpException extends GeoIp2Exception
string $message,
int $httpStatus,
string $uri,
\Exception $previous = null
?\Exception $previous = null
) {
$this->uri = $uri;
parent::__construct($message, $httpStatus, $previous);
@@ -20,7 +20,7 @@ class InvalidRequestException extends HttpException
string $error,
int $httpStatus,
string $uri,
\Exception $previous = null
?\Exception $previous = null
) {
$this->error = $error;
parent::__construct($message, $httpStatus, $uri, $previous);
+11 -18
View File
@@ -64,6 +64,8 @@ class AnonymousIp implements \JsonSerializable
/**
* @ignore
*
* @param array<string, mixed> $raw
*/
public function __construct(array $raw)
{
@@ -78,27 +80,18 @@ class AnonymousIp implements \JsonSerializable
$this->network = Util::cidr($ipAddress, $raw['prefix_len']);
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = [];
if ($this->isAnonymous !== null) {
$js['is_anonymous'] = $this->isAnonymous;
}
if ($this->isAnonymousVpn !== null) {
$js['is_anonymous_vpn'] = $this->isAnonymousVpn;
}
if ($this->isHostingProvider !== null) {
$js['is_hosting_provider'] = $this->isHostingProvider;
}
if ($this->isPublicProxy !== null) {
$js['is_public_proxy'] = $this->isPublicProxy;
}
if ($this->isResidentialProxy !== null) {
$js['is_residential_proxy'] = $this->isResidentialProxy;
}
if ($this->isTorExitNode !== null) {
$js['is_tor_exit_node'] = $this->isTorExitNode;
}
$js['is_anonymous'] = $this->isAnonymous;
$js['is_anonymous_vpn'] = $this->isAnonymousVpn;
$js['is_hosting_provider'] = $this->isHostingProvider;
$js['is_public_proxy'] = $this->isPublicProxy;
$js['is_residential_proxy'] = $this->isResidentialProxy;
$js['is_tor_exit_node'] = $this->isTorExitNode;
$js['ip_address'] = $this->ipAddress;
$js['network'] = $this->network;
+5
View File
@@ -39,6 +39,8 @@ class Asn implements \JsonSerializable
/**
* @ignore
*
* @param array<string, mixed> $raw
*/
public function __construct(array $raw)
{
@@ -50,6 +52,9 @@ class Asn implements \JsonSerializable
$this->network = Util::cidr($ipAddress, $raw['prefix_len']);
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = [];
+39 -25
View File
@@ -4,6 +4,11 @@ declare(strict_types=1);
namespace GeoIp2\Model;
use GeoIp2\Record\City as CityRecord;
use GeoIp2\Record\Location;
use GeoIp2\Record\Postal;
use GeoIp2\Record\Subdivision;
/**
* Model class for the data returned by City Plus web service and City
* database.
@@ -14,57 +19,63 @@ namespace GeoIp2\Model;
class City extends Country
{
/**
* @var \GeoIp2\Record\City city data for the requested IP
* address
* @var CityRecord city data for the requested IP address
*/
public readonly \GeoIp2\Record\City $city;
public readonly CityRecord $city;
/**
* @var \GeoIp2\Record\Location location data for the
* requested IP address
* @var Location location data for the requested IP address
*/
public readonly \GeoIp2\Record\Location $location;
public readonly Location $location;
/**
* @var \GeoIp2\Record\Subdivision An object
* representing the most specific subdivision returned. If the response
* did not contain any subdivisions, this method returns an empty
* \GeoIp2\Record\Subdivision object.
* @var Subdivision An object representing the most specific subdivision
* returned. If the response did not contain any
* subdivisions, this method returns an empty
* \GeoIp2\Record\Subdivision object.
*/
public readonly \GeoIp2\Record\Subdivision $mostSpecificSubdivision;
public readonly Subdivision $mostSpecificSubdivision;
/**
* @var \GeoIp2\Record\Postal postal data for the
* requested IP address
* @var Postal postal data for the
* requested IP address
*/
public readonly \GeoIp2\Record\Postal $postal;
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.
* 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;
/**
* @ignore
*
* @param array<string, mixed> $raw
* @param list<string> $locales
*/
public function __construct(array $raw, array $locales = ['en'])
{
parent::__construct($raw, $locales);
$this->city = new \GeoIp2\Record\City($raw['city'] ?? [], $locales);
$this->location = new \GeoIp2\Record\Location($raw['location'] ?? []);
$this->postal = new \GeoIp2\Record\Postal($raw['postal'] ?? []);
$this->city = new CityRecord($raw['city'] ?? [], $locales);
$this->location = new Location($raw['location'] ?? []);
$this->postal = new Postal($raw['postal'] ?? []);
if (!isset($raw['subdivisions'])) {
$this->subdivisions = [];
$this->mostSpecificSubdivision =
new \GeoIp2\Record\Subdivision([], $locales);
new Subdivision([], $locales);
return;
}
@@ -72,7 +83,7 @@ class City extends Country
$subdivisions = [];
foreach ($raw['subdivisions'] as $sub) {
$subdivisions[] =
new \GeoIp2\Record\Subdivision($sub, $locales)
new Subdivision($sub, $locales)
;
}
@@ -82,6 +93,9 @@ class City extends Country
$this->subdivisions = $subdivisions;
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = parent::jsonSerialize();
@@ -33,6 +33,8 @@ class ConnectionType implements \JsonSerializable
/**
* @ignore
*
* @param array<string, mixed> $raw
*/
public function __construct(array $raw)
{
@@ -42,6 +44,9 @@ class ConnectionType implements \JsonSerializable
$this->network = Util::cidr($ipAddress, $raw['prefix_len']);
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = [];
+39 -28
View File
@@ -4,6 +4,12 @@ declare(strict_types=1);
namespace GeoIp2\Model;
use GeoIp2\Record\Continent;
use GeoIp2\Record\Country as CountryRecord;
use GeoIp2\Record\MaxMind;
use GeoIp2\Record\RepresentedCountry;
use GeoIp2\Record\Traits;
/**
* Model class for the data returned by GeoIP2 Country web service and database.
*
@@ -12,70 +18,75 @@ namespace GeoIp2\Model;
class Country implements \JsonSerializable
{
/**
* @var \GeoIp2\Record\Continent continent data for the
* requested IP address
* @var Continent continent data for the requested IP address
*/
public readonly \GeoIp2\Record\Continent $continent;
public readonly Continent $continent;
/**
* @var \GeoIp2\Record\Country Country data for the requested
* IP address. This object represents the country where MaxMind believes the
* end user is located.
* @var CountryRecord Country data for the requested IP address. This
* object represents the country where MaxMind believes
* the end user is located.
*/
public readonly \GeoIp2\Record\Country $country;
public readonly CountryRecord $country;
/**
* @var \GeoIp2\Record\MaxMind data related to your MaxMind
* account
* @var MaxMind data related to your MaxMind account
*/
public readonly \GeoIp2\Record\MaxMind $maxmind;
public readonly MaxMind $maxmind;
/**
* @var \GeoIp2\Record\Country Registered country
* data for the requested IP address. This record represents the country
* where the ISP has registered a given IP block and may differ from the
* user's country.
* @var CountryRecord Registered country data for the requested IP address.
* This record represents the country where the ISP has
* registered a given IP block and may differ from the
* user's country.
*/
public readonly \GeoIp2\Record\Country $registeredCountry;
public readonly CountryRecord $registeredCountry;
/**
* @var \GeoIp2\Record\RepresentedCountry * Represented country data for the requested IP address. The represented
* country is used for things like military bases. It is only present when
* the represented country differs from the country.
* @var RepresentedCountry Represented country data for the requested IP
* address. The represented country is used for
* things like military bases. It is only present
* when the represented country differs from the
* country.
*/
public readonly \GeoIp2\Record\RepresentedCountry $representedCountry;
public readonly RepresentedCountry $representedCountry;
/**
* @var \GeoIp2\Record\Traits data for the traits of the
* requested IP address
* @var Traits data for the traits of the requested IP address
*/
public readonly \GeoIp2\Record\Traits $traits;
public readonly Traits $traits;
/**
* @ignore
*
* @param array<string, mixed> $raw
* @param list<string> $locales
*/
public function __construct(array $raw, array $locales = ['en'])
{
$this->continent = new \GeoIp2\Record\Continent(
$this->continent = new Continent(
$raw['continent'] ?? [],
$locales
);
$this->country = new \GeoIp2\Record\Country(
$this->country = new CountryRecord(
$raw['country'] ?? [],
$locales
);
$this->maxmind = new \GeoIp2\Record\MaxMind($raw['maxmind'] ?? []);
$this->registeredCountry = new \GeoIp2\Record\Country(
$this->maxmind = new MaxMind($raw['maxmind'] ?? []);
$this->registeredCountry = new CountryRecord(
$raw['registered_country'] ?? [],
$locales
);
$this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
$this->representedCountry = new RepresentedCountry(
$raw['represented_country'] ?? [],
$locales
);
$this->traits = new \GeoIp2\Record\Traits($raw['traits'] ?? []);
$this->traits = new Traits($raw['traits'] ?? []);
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = [];
+5
View File
@@ -33,6 +33,8 @@ class Domain implements \JsonSerializable
/**
* @ignore
*
* @param array<string, mixed> $raw
*/
public function __construct(array $raw)
{
@@ -42,6 +44,9 @@ class Domain implements \JsonSerializable
$this->network = Util::cidr($ipAddress, $raw['prefix_len']);
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = [];
+5
View File
@@ -65,6 +65,8 @@ class Isp implements \JsonSerializable
/**
* @ignore
*
* @param array<string, mixed> $raw
*/
public function __construct(array $raw)
{
@@ -81,6 +83,9 @@ class Isp implements \JsonSerializable
$this->network = Util::cidr($ipAddress, $raw['prefix_len']);
}
/**
* @return array<string, mixed>|null
*/
public function jsonSerialize(): ?array
{
$js = [];
+2 -2
View File
@@ -9,14 +9,14 @@ interface ProviderInterface
/**
* @param string $ipAddress an IPv4 or IPv6 address to lookup
*
* @return \GeoIp2\Model\Country a Country model for the requested IP address
* @return Model\Country a Country model for the requested IP address
*/
public function country(string $ipAddress): Model\Country;
/**
* @param string $ipAddress an IPv4 or IPv6 address to lookup
*
* @return \GeoIp2\Model\City a City model for the requested IP address
* @return Model\City a City model for the requested IP address
*/
public function city(string $ipAddress): Model\City;
}
@@ -14,14 +14,17 @@ abstract class AbstractNamedRecord implements \JsonSerializable
public readonly ?string $name;
/**
* @var array An array map where the keys are locale codes
* and the values are names. This attribute is returned by all location
* services and databases.
* @var array<string, string> An array map where the keys are locale codes
* and the values are names. This attribute is returned by all location
* services and databases.
*/
public readonly array $names;
/**
* @ignore
*
* @param array<string, mixed> $record
* @param list<string> $locales
*/
public function __construct(array $record, array $locales = ['en'])
{
@@ -37,6 +40,9 @@ abstract class AbstractNamedRecord implements \JsonSerializable
$this->name = null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = [];
@@ -21,6 +21,9 @@ abstract class AbstractPlaceRecord extends AbstractNamedRecord
/**
* @ignore
*
* @param array<string, mixed> $record
* @param list<string> $locales
*/
public function __construct(array $record, array $locales = ['en'])
{
@@ -30,6 +33,9 @@ abstract class AbstractPlaceRecord extends AbstractNamedRecord
$this->geonameId = $record['geoname_id'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
@@ -26,6 +26,9 @@ class Continent extends AbstractNamedRecord
/**
* @ignore
*
* @param array<string, mixed> $record
* @param list<string> $locales
*/
public function __construct(array $record, array $locales = ['en'])
{
@@ -35,6 +38,9 @@ class Continent extends AbstractNamedRecord
$this->geonameId = $record['geoname_id'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
@@ -27,6 +27,9 @@ class Country extends AbstractPlaceRecord
/**
* @ignore
*
* @param array<string, mixed> $record
* @param list<string> $locales
*/
public function __construct(array $record, array $locales = ['en'])
{
@@ -36,6 +39,9 @@ class Country extends AbstractPlaceRecord
$this->isoCode = $record['iso_code'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
@@ -64,6 +64,11 @@ class Location implements \JsonSerializable
*/
public readonly ?string $timeZone;
/**
* @ignore
*
* @param array<string, mixed> $record
*/
public function __construct(array $record)
{
$this->averageIncome = $record['average_income'] ?? null;
@@ -75,6 +80,9 @@ class Location implements \JsonSerializable
$this->timeZone = $record['time_zone'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = [];
@@ -17,11 +17,19 @@ class MaxMind implements \JsonSerializable
*/
public readonly ?int $queriesRemaining;
/**
* @ignore
*
* @param array<string, mixed> $record
*/
public function __construct(array $record)
{
$this->queriesRemaining = $record['queries_remaining'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = [];
+5
View File
@@ -30,6 +30,8 @@ class Postal implements \JsonSerializable
/**
* @ignore
*
* @param array<string, mixed> $record
*/
public function __construct(array $record)
{
@@ -37,6 +39,9 @@ class Postal implements \JsonSerializable
$this->confidence = $record['confidence'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = [];
@@ -22,6 +22,9 @@ class RepresentedCountry extends Country
/**
* @ignore
*
* @param array<string, mixed> $record
* @param list<string> $locales
*/
public function __construct(array $record, array $locales = ['en'])
{
@@ -30,6 +33,9 @@ class RepresentedCountry extends Country
$this->type = $record['type'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
@@ -22,6 +22,9 @@ class Subdivision extends AbstractPlaceRecord
/**
* @ignore
*
* @param array<string, mixed> $record
* @param list<string> $locales
*/
public function __construct(array $record, array $locales = ['en'])
{
@@ -30,6 +33,9 @@ class Subdivision extends AbstractPlaceRecord
$this->isoCode = $record['iso_code'] ?? null;
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
+8
View File
@@ -196,6 +196,11 @@ class Traits implements \JsonSerializable
*/
public readonly ?string $userType;
/**
* @ignore
*
* @param array<string, mixed> $record
*/
public function __construct(array $record)
{
$this->autonomousSystemNumber = $record['autonomous_system_number'] ?? null;
@@ -226,6 +231,9 @@ class Traits implements \JsonSerializable
}
}
/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
$js = [];
+77 -77
View File
@@ -14,6 +14,9 @@ use GeoIp2\Model\City;
use GeoIp2\Model\Country;
use GeoIp2\Model\Insights;
use GeoIp2\ProviderInterface;
use MaxMind\Exception\InsufficientFundsException;
use MaxMind\Exception\IpAddressNotFoundException;
use MaxMind\Exception\WebServiceException;
use MaxMind\WebService\Client as WsClient;
/**
@@ -55,30 +58,30 @@ class Client implements ProviderInterface
private WsClient $client;
private static string $basePath = '/geoip/v2.1';
public const VERSION = 'v3.0.0';
public const VERSION = 'v3.1.0';
/**
* Constructor.
*
* @param int $accountId your MaxMind account ID
* @param string $licenseKey your MaxMind license key
* @param array $locales list of locale codes to use in name property
* from most preferred to least preferred
* @param array $options array of options. Valid options include:
* * `host` - The host to use when querying the web
* service. To query the GeoLite2 web service
* instead of the GeoIP2 web service, set the
* host to `geolite.info`. To query the Sandbox
* GeoIP2 web service instead of the production
* GeoIP2 web service, set the host to
* `sandbox.maxmind.com`. The sandbox allows you to
* experiment with the API without affecting your
* production data.
* * `timeout` - Timeout in seconds.
* * `connectTimeout` - Initial connection timeout in seconds.
* * `proxy` - The HTTP proxy to use. May include a schema, port,
* username, and password, e.g.,
* `http://username:[email protected]:10`.
* @param int $accountId your MaxMind account ID
* @param string $licenseKey your MaxMind license key
* @param list<string> $locales list of locale codes to use in name property
* from most preferred to least preferred
* @param array<string, mixed> $options array of options. Valid options include:
* * `host` - The host to use when querying the web
* service. To query the GeoLite2 web service
* instead of the GeoIP2 web service, set the
* host to `geolite.info`. To query the Sandbox
* GeoIP2 web service instead of the production
* GeoIP2 web service, set the host to
* `sandbox.maxmind.com`. The sandbox allows you to
* experiment with the API without affecting your
* production data.
* * `timeout` - Timeout in seconds.
* * `connectTimeout` - Initial connection timeout in seconds.
* * `proxy` - The HTTP proxy to use. May include a schema, port,
* username, and password, e.g.,
* `http://username:[email protected]:10`.
*/
public function __construct(
int $accountId,
@@ -116,24 +119,23 @@ class Client implements ProviderInterface
* address is provided, the address that the web service is called
* from will be used.
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
* provided is not in our database (e.g., a private address).
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
* with the account ID or license key that you provided
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
* of queries
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
* invalid for some other reason. This may indicate an issue
* with this API. Please report the error to MaxMind.
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
* This could indicate a problem with the connection between
* your server and the web service or that the web service
* returned an invalid document or 500 error code
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
* class to the above exceptions. It will be thrown directly
* if a 200 status code is returned but the body is invalid.
* @throws \InvalidArgumentException if something other than a single IP address or "me" is
* passed to the method
* @throws AddressNotFoundException if the address you provided is not in our database (e.g.,
* a private address).
* @throws AuthenticationException if there is a problem with the account ID or license key
* that you provided
* @throws OutOfQueriesException if your account is out of queries
* @throws InvalidRequestException if your request was received by the web service but is
* invalid for some other reason. This may indicate an issue
* with this API. Please report the error to MaxMind.
* @throws HttpException if an unexpected HTTP error code or message was returned.
* This could indicate a problem with the connection between
* your server and the web service or that the web service
* returned an invalid document or 500 error code
* @throws GeoIp2Exception This serves as the parent
* class to the above exceptions. It will be thrown directly
* if a 200 status code is returned but the body is invalid.
* @throws \InvalidArgumentException if something other than a single IP address or "me" is
* passed to the method
*/
public function city(string $ipAddress = 'me'): City
{
@@ -148,24 +150,23 @@ class Client implements ProviderInterface
* address is provided, the address that the web service is called
* from will be used.
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you provided is not in our database (e.g.,
* a private address).
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
* with the account ID or license key that you provided
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out of queries
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
* invalid for some other reason. This may indicate an
* issue with this API. Please report the error to MaxMind.
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
* code or message was returned. This could indicate a problem
* with the connection between your server and the web service
* or that the web service returned an invalid document or 500
* error code.
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent class to the above exceptions. It
* will be thrown directly if a 200 status code is returned but
* the body is invalid.
* @throws \InvalidArgumentException if something other than a single IP address or "me" is
* passed to the method
* @throws AddressNotFoundException if the address you provided is not in our database (e.g.,
* a private address).
* @throws AuthenticationException if there is a problem with the account ID or license key that you provided
* @throws OutOfQueriesException if your account is out of queries
* @throws InvalidRequestException if your request was received by the web service but is
* invalid for some other reason. This may indicate an
* issue with this API. Please report the error to MaxMind.
* @throws HttpException if an unexpected HTTP error
* code or message was returned. This could indicate a problem
* with the connection between your server and the web service
* or that the web service returned an invalid document or 500
* error code.
* @throws GeoIp2Exception This serves as the parent class to the above exceptions. It
* will be thrown directly if a 200 status code is returned but
* the body is invalid.
* @throws \InvalidArgumentException if something other than a single IP address or "me" is
* passed to the method
*/
public function country(string $ipAddress = 'me'): Country
{
@@ -180,24 +181,23 @@ class Client implements ProviderInterface
* address is provided, the address that the web service is called
* from will be used.
*
* @throws \GeoIp2\Exception\AddressNotFoundException if the address you
* provided is not in our database (e.g., a private address).
* @throws \GeoIp2\Exception\AuthenticationException if there is a problem
* with the account ID or license key that you provided
* @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
* of queries
* @throws \GeoIp2\Exception\InvalidRequestException} if your request was received by the web service but is
* invalid for some other reason. This may indicate an
* issue with this API. Please report the error to MaxMind.
* @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error code or message was returned.
* This could indicate a problem with the connection between
* your server and the web service or that the web service
* returned an invalid document or 500 error code
* @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
* class to the above exceptions. It will be thrown directly
* if a 200 status code is returned but the body is invalid.
* @throws \InvalidArgumentException if something other than a single IP address or "me" is
* passed to the method
* @throws AddressNotFoundException if the address you provided is not in our database (e.g.,
* a private address).
* @throws AuthenticationException if there is a problem with the account ID or license key
* that you provided
* @throws OutOfQueriesException if your account is out of queries
* @throws InvalidRequestException if your request was received by the web service but is
* invalid for some other reason. This may indicate an
* issue with this API. Please report the error to MaxMind.
* @throws HttpException if an unexpected HTTP error code or message was returned.
* This could indicate a problem with the connection between
* your server and the web service or that the web service
* returned an invalid document or 500 error code
* @throws GeoIp2Exception This serves as the parent
* class to the above exceptions. It will be thrown directly
* if a 200 status code is returned but the body is invalid.
* @throws \InvalidArgumentException if something other than a single IP address or "me" is
* passed to the method
*/
public function insights(string $ipAddress = 'me'): Insights
{
@@ -217,7 +217,7 @@ class Client implements ProviderInterface
try {
$service = (new \ReflectionClass($class))->getShortName();
$body = $this->client->get('GeoIP2 ' . $service, $path);
} catch (\MaxMind\Exception\IpAddressNotFoundException $ex) {
} catch (IpAddressNotFoundException $ex) {
throw new AddressNotFoundException(
$ex->getMessage(),
$ex->getStatusCode(),
@@ -229,7 +229,7 @@ class Client implements ProviderInterface
$ex->getStatusCode(),
$ex
);
} catch (\MaxMind\Exception\InsufficientFundsException $ex) {
} catch (InsufficientFundsException $ex) {
throw new OutOfQueriesException(
$ex->getMessage(),
$ex->getStatusCode(),
@@ -250,7 +250,7 @@ class Client implements ProviderInterface
$ex->getUri(),
$ex
);
} catch (\MaxMind\Exception\WebServiceException $ex) {
} catch (WebServiceException $ex) {
throw new GeoIp2Exception(
$ex->getMessage(),
$ex->getCode(),
+7
View File
@@ -1,6 +1,13 @@
CHANGELOG
=========
1.12.0 (2024-11-14)
-------------------
* Improve the error handling when the user tries to open a directory
with the pure PHP reader.
* Improve the typehints on arrays in the PHPDocs.
1.11.1 (2023-12-01)
-------------------
+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-2023 by MaxMind, Inc.
This software is Copyright (c) 2014-2024 by MaxMind, Inc.
This is free software, licensed under the Apache License, Version 2.0.
+1 -3
View File
@@ -21,13 +21,11 @@
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
},
"conflict": {
"ext-maxminddb": "<1.11.1,>=2.0.0"
"ext-maxminddb": "<1.11.1 || >=2.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
"phpunit/phpunit": ">=8.0.0,<10.0.0",
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpcov": ">=6.0.0",
"squizlabs/php_codesniffer": "3.*",
"phpstan/phpstan": "*"
},
+20 -13
View File
@@ -64,8 +64,7 @@ class Reader
* Constructs a Reader for the MaxMind DB format. The file passed to it must
* be a valid MaxMind DB file such as a GeoIp2 database file.
*
* @param string $database
* the MaxMind DB file to use
* @param string $database the MaxMind DB file to use
*
* @throws \InvalidArgumentException for invalid database path or unknown arguments
* @throws InvalidDatabaseException
@@ -76,7 +75,14 @@ class Reader
{
if (\func_num_args() !== 1) {
throw new \ArgumentCountError(
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
\sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
);
}
if (is_dir($database)) {
// This matches the error that the C extension throws.
throw new InvalidDatabaseException(
"Error opening database file ($database). Is this a valid MaxMind DB file?"
);
}
@@ -110,8 +116,7 @@ class Reader
/**
* Retrieves the record for the IP address.
*
* @param string $ipAddress
* the IP address to look up
* @param string $ipAddress the IP address to look up
*
* @throws \BadMethodCallException if this method is called on a closed database
* @throws \InvalidArgumentException if something other than a single IP address is passed to the method
@@ -125,7 +130,7 @@ class Reader
{
if (\func_num_args() !== 1) {
throw new \ArgumentCountError(
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
\sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
);
}
[$record] = $this->getWithPrefixLen($ipAddress);
@@ -136,8 +141,7 @@ class Reader
/**
* Retrieves the record for the IP address and its associated network prefix length.
*
* @param string $ipAddress
* the IP address to look up
* @param string $ipAddress the IP address to look up
*
* @throws \BadMethodCallException if this method is called on a closed database
* @throws \InvalidArgumentException if something other than a single IP address is passed to the method
@@ -145,14 +149,14 @@ class Reader
* if the database is invalid or there is an error reading
* from it
*
* @return array an array where the first element is the record and the
* second the network prefix length for the record
* @return array{0:mixed, 1:int} an array where the first element is the record and the
* second the network prefix length for the record
*/
public function getWithPrefixLen(string $ipAddress): array
{
if (\func_num_args() !== 1) {
throw new \ArgumentCountError(
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
\sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
);
}
@@ -170,6 +174,9 @@ class Reader
return [$this->resolveDataPointer($pointer), $prefixLen];
}
/**
* @return array{0:int, 1:int}
*/
private function findAddressInTree(string $ipAddress): array
{
$packedAddr = @inet_pton($ipAddress);
@@ -364,7 +371,7 @@ class Reader
{
if (\func_num_args()) {
throw new \ArgumentCountError(
sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
\sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
);
}
@@ -389,7 +396,7 @@ class Reader
{
if (\func_num_args()) {
throw new \ArgumentCountError(
sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
\sprintf('%s() expects exactly 0 parameters, %d given', __METHOD__, \func_num_args())
);
}
@@ -63,6 +63,9 @@ class Decoder
$this->switchByteOrder = $this->isPlatformLittleEndian();
}
/**
* @return array<mixed>
*/
public function decode(int $offset): array
{
$ctrlByte = \ord(Util::read($this->fileStream, $offset, 1));
@@ -110,6 +113,8 @@ class Decoder
/**
* @param int<0, max> $size
*
* @return array{0:mixed, 1:int}
*/
private function decodeByType(int $type, int $offset, int $size): array
{
@@ -167,6 +172,9 @@ class Decoder
}
}
/**
* @return array{0:array<mixed>, 1:int}
*/
private function decodeArray(int $size, int $offset): array
{
$array = [];
@@ -247,6 +255,9 @@ class Decoder
return $int;
}
/**
* @return array{0:array<string, mixed>, 1:int}
*/
private function decodeMap(int $size, int $offset): array
{
$map = [];
@@ -260,6 +271,9 @@ class Decoder
return [$map, $offset];
}
/**
* @return array{0:int, 1:int}
*/
private function decodePointer(int $ctrlByte, int $offset): array
{
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
@@ -378,6 +392,9 @@ class Decoder
return $integerAsString;
}
/**
* @return array{0:int, 1:int}
*/
private function sizeFromCtrlByte(int $ctrlByte, int $offset): array
{
$size = $ctrlByte & 0x1F;
@@ -48,7 +48,7 @@ class Metadata
* in that language as a UTF-8 string. May be undefined for some
* databases.
*
* @var array
* @var array<string, string>
*/
public $description;
@@ -65,7 +65,7 @@ class Metadata
* may contain data items that have been localized to some or all of
* these languages. This may be undefined.
*
* @var array
* @var array<string>
*/
public $languages;
@@ -95,11 +95,14 @@ class Metadata
*/
public $searchTreeSize;
/**
* @param array<string, mixed> $metadata
*/
public function __construct(array $metadata)
{
if (\func_num_args() !== 1) {
throw new \ArgumentCountError(
sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
\sprintf('%s() expects exactly 1 parameter, %d given', __METHOD__, \func_num_args())
);
}
+2 -2
View File
@@ -388,7 +388,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.0.0</version>
<version>3.1.0</version>
<license>Apache</license>
<licenseversion>2.0</licenseversion>
<repository>https://github.com/maxmind/GeoIP2-php</repository>
@@ -400,7 +400,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.11.1</version>
<version>1.12.0</version>
<license>Apache</license>
<licenseversion>2.0</licenseversion>
<repository>https://github.com/maxmind/MaxMind-DB-Reader-php/</repository>