diff --git a/lib/maxmind/GeoIp2/Database/Reader.php b/lib/maxmind/GeoIp2/Database/Reader.php index 0c370b730fe..4dabc5d15c4 100644 --- a/lib/maxmind/GeoIp2/Database/Reader.php +++ b/lib/maxmind/GeoIp2/Database/Reader.php @@ -5,6 +5,15 @@ declare(strict_types=1); namespace GeoIp2\Database; use GeoIp2\Exception\AddressNotFoundException; +use GeoIp2\Model\AbstractModel; +use GeoIp2\Model\AnonymousIp; +use GeoIp2\Model\Asn; +use GeoIp2\Model\City; +use GeoIp2\Model\ConnectionType; +use GeoIp2\Model\Country; +use GeoIp2\Model\Domain; +use GeoIp2\Model\Enterprise; +use GeoIp2\Model\Isp; use GeoIp2\ProviderInterface; use MaxMind\Db\Reader as DbReader; use MaxMind\Db\Reader\InvalidDatabaseException; @@ -35,8 +44,19 @@ use MaxMind\Db\Reader\InvalidDatabaseException; */ class Reader implements ProviderInterface { + /** + * @var DbReader + */ private $dbReader; + + /** + * @var string + */ private $dbType; + + /** + * @var array + */ private $locales; /** @@ -68,9 +88,10 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function city(string $ipAddress): \GeoIp2\Model\City + public function city(string $ipAddress): City { - return $this->modelFor('City', 'City', $ipAddress); + // @phpstan-ignore-next-line + return $this->modelFor(City::class, 'City', $ipAddress); } /** @@ -83,9 +104,10 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function country(string $ipAddress): \GeoIp2\Model\Country + public function country(string $ipAddress): Country { - return $this->modelFor('Country', 'Country', $ipAddress); + // @phpstan-ignore-next-line + return $this->modelFor(Country::class, 'Country', $ipAddress); } /** @@ -98,10 +120,11 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function anonymousIp(string $ipAddress): \GeoIp2\Model\AnonymousIp + public function anonymousIp(string $ipAddress): AnonymousIp { + // @phpstan-ignore-next-line return $this->flatModelFor( - 'AnonymousIp', + AnonymousIp::class, 'GeoIP2-Anonymous-IP', $ipAddress ); @@ -117,10 +140,11 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function asn(string $ipAddress): \GeoIp2\Model\Asn + public function asn(string $ipAddress): Asn { + // @phpstan-ignore-next-line return $this->flatModelFor( - 'Asn', + Asn::class, 'GeoLite2-ASN', $ipAddress ); @@ -136,10 +160,11 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function connectionType(string $ipAddress): \GeoIp2\Model\ConnectionType + public function connectionType(string $ipAddress): ConnectionType { + // @phpstan-ignore-next-line return $this->flatModelFor( - 'ConnectionType', + ConnectionType::class, 'GeoIP2-Connection-Type', $ipAddress ); @@ -155,10 +180,11 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function domain(string $ipAddress): \GeoIp2\Model\Domain + public function domain(string $ipAddress): Domain { + // @phpstan-ignore-next-line return $this->flatModelFor( - 'Domain', + Domain::class, 'GeoIP2-Domain', $ipAddress ); @@ -174,9 +200,10 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function enterprise(string $ipAddress): \GeoIp2\Model\Enterprise + public function enterprise(string $ipAddress): Enterprise { - return $this->modelFor('Enterprise', 'Enterprise', $ipAddress); + // @phpstan-ignore-next-line + return $this->modelFor(Enterprise::class, 'Enterprise', $ipAddress); } /** @@ -189,34 +216,32 @@ class Reader implements ProviderInterface * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database * is corrupt or invalid */ - public function isp(string $ipAddress): \GeoIp2\Model\Isp + public function isp(string $ipAddress): Isp { + // @phpstan-ignore-next-line return $this->flatModelFor( - 'Isp', + Isp::class, 'GeoIP2-ISP', $ipAddress ); } - private function modelFor(string $class, string $type, string $ipAddress) + private function modelFor(string $class, string $type, string $ipAddress): AbstractModel { - list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress); + [$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress); $record['traits']['ip_address'] = $ipAddress; $record['traits']['prefix_len'] = $prefixLen; - $class = 'GeoIp2\\Model\\' . $class; - return new $class($record, $this->locales); } - private function flatModelFor(string $class, string $type, string $ipAddress) + private function flatModelFor(string $class, string $type, string $ipAddress): AbstractModel { - list($record, $prefixLen) = $this->getRecord($class, $type, $ipAddress); + [$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress); $record['ip_address'] = $ipAddress; $record['prefix_len'] = $prefixLen; - $class = 'GeoIp2\\Model\\' . $class; return new $class($record); } @@ -224,12 +249,13 @@ class Reader implements ProviderInterface private function getRecord(string $class, string $type, string $ipAddress): array { if (strpos($this->dbType, $type) === false) { - $method = lcfirst($class); + $method = lcfirst((new \ReflectionClass($class))->getShortName()); + throw new \BadMethodCallException( "The $method method cannot be used to open a {$this->dbType} database" ); } - list($record, $prefixLen) = $this->dbReader->getWithPrefixLen($ipAddress); + [$record, $prefixLen] = $this->dbReader->getWithPrefixLen($ipAddress); if ($record === null) { throw new AddressNotFoundException( "The address $ipAddress is not in the database." @@ -258,7 +284,7 @@ class Reader implements ProviderInterface * * @return \MaxMind\Db\Reader\Metadata object for the database */ - public function metadata(): \MaxMind\Db\Reader\Metadata + public function metadata(): DbReader\Metadata { return $this->dbReader->metadata(); } diff --git a/lib/maxmind/GeoIp2/Exception/HttpException.php b/lib/maxmind/GeoIp2/Exception/HttpException.php index 955e595af20..c11d4410880 100644 --- a/lib/maxmind/GeoIp2/Exception/HttpException.php +++ b/lib/maxmind/GeoIp2/Exception/HttpException.php @@ -11,6 +11,8 @@ class HttpException extends GeoIp2Exception { /** * The URI queried. + * + * @var string */ public $uri; diff --git a/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php b/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php index e469f56ccd7..925b68df00b 100644 --- a/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php +++ b/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php @@ -12,6 +12,8 @@ class InvalidRequestException extends HttpException { /** * The code returned by the MaxMind web service. + * + * @var string */ public $error; diff --git a/lib/maxmind/GeoIp2/Model/AbstractModel.php b/lib/maxmind/GeoIp2/Model/AbstractModel.php index d58639c9431..27f3e2a4400 100644 --- a/lib/maxmind/GeoIp2/Model/AbstractModel.php +++ b/lib/maxmind/GeoIp2/Model/AbstractModel.php @@ -9,6 +9,9 @@ namespace GeoIp2\Model; */ abstract class AbstractModel implements \JsonSerializable { + /** + * @var array + */ protected $raw; /** @@ -21,6 +24,8 @@ abstract class AbstractModel implements \JsonSerializable /** * @ignore + * + * @return mixed */ protected function get(string $field) { @@ -36,11 +41,13 @@ abstract class AbstractModel implements \JsonSerializable /** * @ignore + * + * @return mixed */ public function __get(string $attr) { if ($attr !== 'instance' && property_exists($this, $attr)) { - return $this->$attr; + return $this->{$attr}; } throw new \RuntimeException("Unknown attribute: $attr"); @@ -51,7 +58,7 @@ abstract class AbstractModel implements \JsonSerializable */ public function __isset(string $attr): bool { - return $attr !== 'instance' && isset($this->$attr); + return $attr !== 'instance' && isset($this->{$attr}); } public function jsonSerialize(): array diff --git a/lib/maxmind/GeoIp2/Model/AnonymousIp.php b/lib/maxmind/GeoIp2/Model/AnonymousIp.php index bdfbc258a33..5586bd00fcb 100644 --- a/lib/maxmind/GeoIp2/Model/AnonymousIp.php +++ b/lib/maxmind/GeoIp2/Model/AnonymousIp.php @@ -31,13 +31,44 @@ use GeoIp2\Util; */ class AnonymousIp extends AbstractModel { + /** + * @var bool + */ protected $isAnonymous; + + /** + * @var bool + */ protected $isAnonymousVpn; + + /** + * @var bool + */ protected $isHostingProvider; + + /** + * @var bool + */ protected $isPublicProxy; + + /** + * @var bool + */ protected $isResidentialProxy; + + /** + * @var bool + */ protected $isTorExitNode; + + /** + * @var string + */ protected $ipAddress; + + /** + * @var string + */ protected $network; /** diff --git a/lib/maxmind/GeoIp2/Model/Asn.php b/lib/maxmind/GeoIp2/Model/Asn.php index 38a0f750c64..f05177eb906 100644 --- a/lib/maxmind/GeoIp2/Model/Asn.php +++ b/lib/maxmind/GeoIp2/Model/Asn.php @@ -22,9 +22,24 @@ use GeoIp2\Util; */ class Asn extends AbstractModel { + /** + * @var int|null + */ protected $autonomousSystemNumber; + + /** + * @var string|null + */ protected $autonomousSystemOrganization; + + /** + * @var string + */ protected $ipAddress; + + /** + * @var string + */ protected $network; /** diff --git a/lib/maxmind/GeoIp2/Model/City.php b/lib/maxmind/GeoIp2/Model/City.php index 1840e778f21..b2e81dccb56 100644 --- a/lib/maxmind/GeoIp2/Model/City.php +++ b/lib/maxmind/GeoIp2/Model/City.php @@ -5,11 +5,11 @@ declare(strict_types=1); namespace GeoIp2\Model; /** - * Model class for the data returned by GeoIP2 City web service and database. + * Model class for the data returned by City Plus web service and City + * database. * - * The only difference between the City and Insights model classes is which - * fields in each record may be populated. See - * https://dev.maxmind.com/geoip/geoip2/web-services for more details. + * See https://dev.maxmind.com/geoip/docs/web-services?lang=en for more + * details. * * @property-read \GeoIp2\Record\City $city City data for the requested IP * address. @@ -33,18 +33,29 @@ class City extends Country { /** * @ignore + * + * @var \GeoIp2\Record\City */ protected $city; + /** * @ignore + * + * @var \GeoIp2\Record\Location */ protected $location; + /** * @ignore + * + * @var \GeoIp2\Record\Postal */ protected $postal; + /** * @ignore + * + * @var array<\GeoIp2\Record\Subdivision> */ protected $subdivisions = []; @@ -69,20 +80,21 @@ class City extends Country } foreach ($raw['subdivisions'] as $sub) { - array_push( - $this->subdivisions, + $this->subdivisions[] = new \GeoIp2\Record\Subdivision($sub, $locales) - ); + ; } } /** * @ignore + * + * @return mixed */ public function __get(string $attr) { if ($attr === 'mostSpecificSubdivision') { - return $this->$attr(); + return $this->{$attr}(); } return parent::__get($attr); diff --git a/lib/maxmind/GeoIp2/Model/ConnectionType.php b/lib/maxmind/GeoIp2/Model/ConnectionType.php index 5f7747fe527..36d4529a208 100644 --- a/lib/maxmind/GeoIp2/Model/ConnectionType.php +++ b/lib/maxmind/GeoIp2/Model/ConnectionType.php @@ -20,8 +20,19 @@ use GeoIp2\Util; */ class ConnectionType extends AbstractModel { + /** + * @var string|null + */ protected $connectionType; + + /** + * @var string + */ protected $ipAddress; + + /** + * @var string + */ protected $network; /** diff --git a/lib/maxmind/GeoIp2/Model/Country.php b/lib/maxmind/GeoIp2/Model/Country.php index d7d07f1cf91..fdffc63f11c 100644 --- a/lib/maxmind/GeoIp2/Model/Country.php +++ b/lib/maxmind/GeoIp2/Model/Country.php @@ -7,9 +7,7 @@ namespace GeoIp2\Model; /** * Model class for the data returned by GeoIP2 Country web service and database. * - * The only difference between the City and Insights model classes is which - * fields in each record may be populated. See - * https://dev.maxmind.com/geoip/geoip2/web-services for more details. + * See https://dev.maxmind.com/geoip/docs/web-services?lang=en for more details. * * @property-read \GeoIp2\Record\Continent $continent Continent data for the * requested IP address. @@ -28,15 +26,43 @@ namespace GeoIp2\Model; * the represented country differs from the country. * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the * requested IP address. + * @property-read array $raw The raw data from the web service. */ class Country extends AbstractModel { + /** + * @var \GeoIp2\Record\Continent + */ protected $continent; + + /** + * @var \GeoIp2\Record\Country + */ protected $country; + + /** + * @var array + */ protected $locales; + + /** + * @var \GeoIp2\Record\MaxMind + */ protected $maxmind; + + /** + * @var \GeoIp2\Record\Country + */ protected $registeredCountry; + + /** + * @var \GeoIp2\Record\RepresentedCountry + */ protected $representedCountry; + + /** + * @var \GeoIp2\Record\Traits + */ protected $traits; /** diff --git a/lib/maxmind/GeoIp2/Model/Domain.php b/lib/maxmind/GeoIp2/Model/Domain.php index e332dd48e1b..067a5076ef1 100644 --- a/lib/maxmind/GeoIp2/Model/Domain.php +++ b/lib/maxmind/GeoIp2/Model/Domain.php @@ -20,8 +20,19 @@ use GeoIp2\Util; */ class Domain extends AbstractModel { + /** + * @var string|null + */ protected $domain; + + /** + * @var string + */ protected $ipAddress; + + /** + * @var string + */ protected $network; /** diff --git a/lib/maxmind/GeoIp2/Model/Enterprise.php b/lib/maxmind/GeoIp2/Model/Enterprise.php index e9706a69812..c63469ba425 100644 --- a/lib/maxmind/GeoIp2/Model/Enterprise.php +++ b/lib/maxmind/GeoIp2/Model/Enterprise.php @@ -7,9 +7,8 @@ namespace GeoIp2\Model; /** * Model class for the data returned by GeoIP2 Enterprise database lookups. * - * The only difference between the City and Enterprise model classes is which - * fields in each record may be populated. See - * https://dev.maxmind.com/geoip/geoip2/web-services for more details. + * See https://dev.maxmind.com/geoip/docs/web-services?lang=en for more + * details. */ class Enterprise extends City { diff --git a/lib/maxmind/GeoIp2/Model/Insights.php b/lib/maxmind/GeoIp2/Model/Insights.php index 589749e6dc3..351c7a5f164 100644 --- a/lib/maxmind/GeoIp2/Model/Insights.php +++ b/lib/maxmind/GeoIp2/Model/Insights.php @@ -5,11 +5,10 @@ declare(strict_types=1); namespace GeoIp2\Model; /** - * Model class for the data returned by GeoIP2 Precision: Insights web service. + * Model class for the data returned by GeoIP2 Insights web service. * - * The only difference between the City and Insights model classes is which - * fields in each record may be populated. See - * https://dev.maxmind.com/geoip/geoip2/web-services for more details. + * See https://dev.maxmind.com/geoip/docs/web-services?lang=en for + * more details. */ class Insights extends City { diff --git a/lib/maxmind/GeoIp2/Model/Isp.php b/lib/maxmind/GeoIp2/Model/Isp.php index 9c28c7f8696..f54efd9bd6a 100644 --- a/lib/maxmind/GeoIp2/Model/Isp.php +++ b/lib/maxmind/GeoIp2/Model/Isp.php @@ -16,6 +16,12 @@ use GeoIp2\Util; * address. * @property-read string|null $isp The name of the ISP associated with the IP * address. + * @property-read string|null $mobileCountryCode The [mobile country code + * (MCC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with + * the IP address and ISP. + * @property-read string|null $mobileNetworkCode The [mobile network code + * (MNC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with + * the IP address and ISP. * @property-read string|null $organization The name of the organization associated * with the IP address. * @property-read string $ipAddress The IP address that the data in the model is @@ -26,11 +32,44 @@ use GeoIp2\Util; */ class Isp extends AbstractModel { + /** + * @var int|null + */ protected $autonomousSystemNumber; + + /** + * @var string|null + */ protected $autonomousSystemOrganization; + + /** + * @var string|null + */ protected $isp; + + /** + * @var string|null + */ + protected $mobileCountryCode; + + /** + * @var string|null + */ + protected $mobileNetworkCode; + + /** + * @var string|null + */ protected $organization; + + /** + * @var string + */ protected $ipAddress; + + /** + * @var string + */ protected $network; /** @@ -43,6 +82,8 @@ class Isp extends AbstractModel $this->autonomousSystemOrganization = $this->get('autonomous_system_organization'); $this->isp = $this->get('isp'); + $this->mobileCountryCode = $this->get('mobile_country_code'); + $this->mobileNetworkCode = $this->get('mobile_network_code'); $this->organization = $this->get('organization'); $ipAddress = $this->get('ip_address'); diff --git a/lib/maxmind/GeoIp2/ProviderInterface.php b/lib/maxmind/GeoIp2/ProviderInterface.php index 4e28eff1bd0..7d148912665 100644 --- a/lib/maxmind/GeoIp2/ProviderInterface.php +++ b/lib/maxmind/GeoIp2/ProviderInterface.php @@ -11,12 +11,12 @@ interface ProviderInterface * * @return \GeoIp2\Model\Country a Country model for the requested IP address */ - public function country(string $ipAddress): \GeoIp2\Model\Country; + 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 */ - public function city(string $ipAddress): \GeoIp2\Model\City; + public function city(string $ipAddress): Model\City; } diff --git a/lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php b/lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php index 767ccb936c7..684ab8c8cca 100644 --- a/lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php +++ b/lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php @@ -6,6 +6,9 @@ namespace GeoIp2\Record; abstract class AbstractPlaceRecord extends AbstractRecord { + /** + * @var array + */ private $locales; /** @@ -19,6 +22,8 @@ abstract class AbstractPlaceRecord extends AbstractRecord /** * @ignore + * + * @return mixed */ public function __get(string $attr) { @@ -45,6 +50,7 @@ abstract class AbstractPlaceRecord extends AbstractRecord { $locale = $this->firstSetNameLocale(); + // @phpstan-ignore-next-line return $locale === null ? null : $this->names[$locale]; } diff --git a/lib/maxmind/GeoIp2/Record/AbstractRecord.php b/lib/maxmind/GeoIp2/Record/AbstractRecord.php index e2abcf16c4c..5ddb3c67929 100644 --- a/lib/maxmind/GeoIp2/Record/AbstractRecord.php +++ b/lib/maxmind/GeoIp2/Record/AbstractRecord.php @@ -6,6 +6,9 @@ namespace GeoIp2\Record; abstract class AbstractRecord implements \JsonSerializable { + /** + * @var array + */ private $record; /** @@ -18,6 +21,8 @@ abstract class AbstractRecord implements \JsonSerializable /** * @ignore + * + * @return mixed */ public function __get(string $attr) { @@ -26,20 +31,22 @@ abstract class AbstractRecord implements \JsonSerializable if ($this->__isset($attr)) { return $this->record[$key]; - } elseif ($this->validAttribute($attr)) { + } + if ($this->validAttribute($attr)) { if (preg_match('/^is_/', $key)) { return false; } return null; } + throw new \RuntimeException("Unknown attribute: $attr"); } public function __isset(string $attr): bool { - return $this->validAttribute($attr) && - isset($this->record[$this->attributeToKey($attr)]); + return $this->validAttribute($attr) + && isset($this->record[$this->attributeToKey($attr)]); } private function attributeToKey(string $attr): string @@ -49,6 +56,7 @@ abstract class AbstractRecord implements \JsonSerializable private function validAttribute(string $attr): bool { + // @phpstan-ignore-next-line return \in_array($attr, $this->validAttributes, true); } diff --git a/lib/maxmind/GeoIp2/Record/City.php b/lib/maxmind/GeoIp2/Record/City.php index ac62bea6e2d..f25dcb389e1 100644 --- a/lib/maxmind/GeoIp2/Record/City.php +++ b/lib/maxmind/GeoIp2/Record/City.php @@ -18,7 +18,7 @@ namespace GeoIp2\Record; * @property-read string|null $name The name of the city based on the locales list * passed to the constructor. This attribute is returned by all location * services and databases. - * @property-read array|null $names A array map where the keys are locale codes + * @property-read array|null $names An array map where the keys are locale codes * and the values are names. This attribute is returned by all location * services and databases. */ @@ -26,6 +26,8 @@ class City extends AbstractPlaceRecord { /** * @ignore + * + * @var array */ protected $validAttributes = ['confidence', 'geonameId', 'names']; } diff --git a/lib/maxmind/GeoIp2/Record/Continent.php b/lib/maxmind/GeoIp2/Record/Continent.php index d6444aca017..103e2e3d840 100644 --- a/lib/maxmind/GeoIp2/Record/Continent.php +++ b/lib/maxmind/GeoIp2/Record/Continent.php @@ -25,6 +25,8 @@ class Continent extends AbstractPlaceRecord { /** * @ignore + * + * @var array */ protected $validAttributes = [ 'code', diff --git a/lib/maxmind/GeoIp2/Record/Country.php b/lib/maxmind/GeoIp2/Record/Country.php index cfbfaef3c3f..3009ebc622b 100644 --- a/lib/maxmind/GeoIp2/Record/Country.php +++ b/lib/maxmind/GeoIp2/Record/Country.php @@ -31,6 +31,8 @@ class Country extends AbstractPlaceRecord { /** * @ignore + * + * @var array */ protected $validAttributes = [ 'confidence', diff --git a/lib/maxmind/GeoIp2/Record/Location.php b/lib/maxmind/GeoIp2/Record/Location.php index 00c40653af5..cb6111c2c44 100644 --- a/lib/maxmind/GeoIp2/Record/Location.php +++ b/lib/maxmind/GeoIp2/Record/Location.php @@ -39,6 +39,8 @@ class Location extends AbstractRecord { /** * @ignore + * + * @var array */ protected $validAttributes = [ 'averageIncome', diff --git a/lib/maxmind/GeoIp2/Record/MaxMind.php b/lib/maxmind/GeoIp2/Record/MaxMind.php index 9c1bbc584a4..e972506e568 100644 --- a/lib/maxmind/GeoIp2/Record/MaxMind.php +++ b/lib/maxmind/GeoIp2/Record/MaxMind.php @@ -16,6 +16,8 @@ class MaxMind extends AbstractRecord { /** * @ignore + * + * @var array */ protected $validAttributes = ['queriesRemaining']; } diff --git a/lib/maxmind/GeoIp2/Record/Postal.php b/lib/maxmind/GeoIp2/Record/Postal.php index d77be2bd87b..3e9c2377b88 100644 --- a/lib/maxmind/GeoIp2/Record/Postal.php +++ b/lib/maxmind/GeoIp2/Record/Postal.php @@ -23,6 +23,8 @@ class Postal extends AbstractRecord { /** * @ignore + * + * @var array */ protected $validAttributes = ['code', 'confidence']; } diff --git a/lib/maxmind/GeoIp2/Record/RepresentedCountry.php b/lib/maxmind/GeoIp2/Record/RepresentedCountry.php index 69bb17b9349..727c034afa2 100644 --- a/lib/maxmind/GeoIp2/Record/RepresentedCountry.php +++ b/lib/maxmind/GeoIp2/Record/RepresentedCountry.php @@ -17,6 +17,11 @@ namespace GeoIp2\Record; */ class RepresentedCountry extends Country { + /** + * @ignore + * + * @var array + */ protected $validAttributes = [ 'confidence', 'geonameId', diff --git a/lib/maxmind/GeoIp2/Record/Subdivision.php b/lib/maxmind/GeoIp2/Record/Subdivision.php index 87b895f55fe..0e83549382a 100644 --- a/lib/maxmind/GeoIp2/Record/Subdivision.php +++ b/lib/maxmind/GeoIp2/Record/Subdivision.php @@ -32,6 +32,8 @@ class Subdivision extends AbstractPlaceRecord { /** * @ignore + * + * @var array */ protected $validAttributes = [ 'confidence', diff --git a/lib/maxmind/GeoIp2/Record/Traits.php b/lib/maxmind/GeoIp2/Record/Traits.php index e8b0d5c0e45..8000d5042e3 100644 --- a/lib/maxmind/GeoIp2/Record/Traits.php +++ b/lib/maxmind/GeoIp2/Record/Traits.php @@ -14,13 +14,13 @@ use GeoIp2\Util; * @property-read int|null $autonomousSystemNumber The autonomous system number * associated with the IP address. See * https://en.wikipedia.org/wiki/Autonomous_system_(Internet%29. This attribute - * is only available from the City and Insights web service and the GeoIP2 - * Enterprise database. + * is only available from the City Plus and Insights web services and the + * GeoIP2 Enterprise database. * @property-read string|null $autonomousSystemOrganization The organization * associated with the registered autonomous system number for the IP address. * See https://en.wikipedia.org/wiki/Autonomous_system_(Internet%29. This - * attribute is only available from the City and Insights web service and the - * GeoIP2 Enterprise database. + * attribute is only available from the City Plus and Insights web services and + * the GeoIP2 Enterprise database. * @property-read string|null $connectionType The connection type may take the * following values: "Dialup", "Cable/DSL", "Corporate", "Cellular". * Additional values may be added in the future. This attribute is only @@ -28,7 +28,7 @@ use GeoIp2\Util; * @property-read string|null $domain The second level domain associated with the * IP address. This will be something like "example.com" or "example.co.uk", * not "foo.example.com". This attribute is only available from the - * City and Insights web service and the GeoIP2 Enterprise + * City Plus and Insights web services and the GeoIP2 Enterprise * database. * @property-read string $ipAddress The IP address that the data in the model * is for. If you performed a "me" lookup against the web service, this @@ -38,7 +38,7 @@ use GeoIp2\Util; * points. * @property-read bool $isAnonymous This is true if the IP address belongs to * any sort of anonymous network. This property is only available from GeoIP2 - * Precision Insights. + * Insights. * @property-read bool $isAnonymousProxy *Deprecated.* Please see our GeoIP2 * Anonymous IP database * (https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine @@ -47,42 +47,49 @@ use GeoIp2\Util; * registered to an anonymous VPN provider. If a VPN provider does not register * subnets under names associated with them, we will likely only flag their IP * ranges using the isHostingProvider property. This property is only available - * from GeoIP2 Precision Insights. + * from GeoIP2 Insights. * @property-read bool $isHostingProvider This is true if the IP address belongs * to a hosting or VPN provider (see description of isAnonymousVpn property). - * This property is only available from GeoIP2 Precision Insights. + * This property is only available from GeoIP2 Insights. * @property-read bool $isLegitimateProxy This attribute is true if MaxMind * believes this IP address to be a legitimate proxy, such as an internal * VPN used by a corporation. This attribute is only available in the GeoIP2 * Enterprise database. * @property-read bool $isPublicProxy This is true if the IP address belongs to - * a public proxy. This property is only available from GeoIP2 Precision - * Insights. + * a public proxy. This property is only available from GeoIP2 Insights. * @property-read bool $isResidentialProxy This is true if the IP address is * on a suspected anonymizing network and belongs to a residential ISP. This - * property is only available from GeoIP2 Precision Insights. + * property is only available from GeoIP2 Insights. * @property-read bool $isSatelliteProvider *Deprecated.* Due to the * increased coverage by mobile carriers, very few satellite providers now * serve multiple countries. As a result, the output does not provide * sufficiently relevant data for us to maintain it. * @property-read bool $isTorExitNode This is true if the IP address is a Tor - * exit node. This property is only available from GeoIP2 Precision Insights. + * exit node. This property is only available from GeoIP2 Insights. * @property-read string|null $isp The name of the ISP associated with the IP - * address. This attribute is only available from the City and Insights web - * services and the GeoIP2 Enterprise database. + * address. This attribute is only available from the City Plus and Insights + * web services and the GeoIP2 Enterprise database. * @property-read string $network The network in CIDR notation associated with * the record. In particular, this is the largest network where all of the * fields besides $ipAddress have the same value. - * @property-read string|null $organization The name of the organization associated - * with the IP address. This attribute is only available from the City and + * @property-read string|null $organization The name of the organization + * associated with the IP address. This attribute is only available from the + * City Plus and Insights web services and the GeoIP2 Enterprise database. + * @property-read string|null $mobileCountryCode The [mobile country code + * (MCC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with + * the IP address and ISP. This property is available from the City Plus and * Insights web services and the GeoIP2 Enterprise database. - * @property-read float|null $staticIPScore An indicator of how static or + * @property-read string|null $mobileNetworkCode The [mobile network code + * (MNC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with + * the IP address and ISP. This property is available from the City Plus and + * Insights web services and the GeoIP2 Enterprise database. + * @property-read float|null $staticIpScore An indicator of how static or * dynamic an IP address is. This property is only available from GeoIP2 - * Precision Insights. + * Insights. * @property-read int|null $userCount The estimated number of users sharing * the IP/network during the past 24 hours. For IPv4, the count is for the * individual IP. For IPv6, the count is for the /64 network. This property is - * only available from GeoIP2 Precision Insights. + * only available from GeoIP2 Insights. * @property-read string|null $userType

The user type associated with the IP * address. This can be one of the following values:

*
    @@ -90,6 +97,7 @@ use GeoIp2\Util; *
  • cafe *
  • cellular *
  • college + *
  • consumer_privacy_network *
  • content_delivery_network *
  • dialup *
  • government @@ -111,6 +119,8 @@ class Traits extends AbstractRecord { /** * @ignore + * + * @var array */ protected $validAttributes = [ 'autonomousSystemNumber', @@ -128,6 +138,8 @@ class Traits extends AbstractRecord 'isResidentialProxy', 'isSatelliteProvider', 'isTorExitNode', + 'mobileCountryCode', + 'mobileNetworkCode', 'network', 'organization', 'staticIpScore', @@ -137,7 +149,7 @@ class Traits extends AbstractRecord public function __construct(?array $record) { - if (!isset($record['network']) && isset($record['ip_address']) && isset($record['prefix_len'])) { + if (!isset($record['network']) && isset($record['ip_address'], $record['prefix_len'])) { $record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']); } diff --git a/lib/maxmind/GeoIp2/WebService/Client.php b/lib/maxmind/GeoIp2/WebService/Client.php index a6801ebdfed..18d979dc617 100644 --- a/lib/maxmind/GeoIp2/WebService/Client.php +++ b/lib/maxmind/GeoIp2/WebService/Client.php @@ -10,13 +10,16 @@ use GeoIp2\Exception\GeoIp2Exception; use GeoIp2\Exception\HttpException; use GeoIp2\Exception\InvalidRequestException; use GeoIp2\Exception\OutOfQueriesException; +use GeoIp2\Model\City; +use GeoIp2\Model\Country; +use GeoIp2\Model\Insights; use GeoIp2\ProviderInterface; use MaxMind\WebService\Client as WsClient; /** - * This class provides a client API for all the GeoIP2 Precision web services. - * The services are Country, City, and Insights. Each service returns a - * different set of data about an IP address, with Country returning the + * This class provides a client API for all the GeoIP2 web services. + * The services are Country, City Plus, and Insights. Each service returns + * a different set of data about an IP address, with Country returning the * least data and Insights the most. * * Each web service is represented by a different model class, and these model @@ -45,11 +48,22 @@ use MaxMind\WebService\Client as WsClient; */ class Client implements ProviderInterface { + /** + * @var array + */ private $locales; + + /** + * @var WsClient + */ private $client; + + /** + * @var string + */ private static $basePath = '/geoip/v2.1'; - const VERSION = 'v2.11.0'; + public const VERSION = 'v2.13.0'; /** * Constructor. @@ -59,7 +73,10 @@ class Client implements ProviderInterface * @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. + * * `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`. * * `timeout` - Timeout in seconds. * * `connectTimeout` - Initial connection timeout in seconds. * * `proxy` - The HTTP proxy to use. May include a schema, port, @@ -76,6 +93,7 @@ class Client implements ProviderInterface // This is for backwards compatibility. Do not remove except for a // major version bump. + // @phpstan-ignore-next-line if (\is_string($options)) { $options = ['host' => $options]; } @@ -95,7 +113,7 @@ class Client implements ProviderInterface } /** - * This method calls the GeoIP2 Precision: City service. + * This method calls the City Plus service. * * @param string $ipAddress IPv4 or IPv6 address as a string. If no * address is provided, the address that the web service is called @@ -110,21 +128,22 @@ class Client implements ProviderInterface * @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 \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. */ - public function city(string $ipAddress = 'me'): \GeoIp2\Model\City + public function city(string $ipAddress = 'me'): City { - return $this->responseFor('city', 'City', $ipAddress); + // @phpstan-ignore-next-line + return $this->responseFor('city', City::class, $ipAddress); } /** - * This method calls the GeoIP2 Precision: Country service. + * This method calls the Country service. * * @param string $ipAddress IPv4 or IPv6 address as a string. If no * address is provided, the address that the web service is called @@ -138,22 +157,23 @@ class Client implements ProviderInterface * @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 \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. */ - public function country(string $ipAddress = 'me'): \GeoIp2\Model\Country + public function country(string $ipAddress = 'me'): Country { - return $this->responseFor('country', 'Country', $ipAddress); + return $this->responseFor('country', Country::class, $ipAddress); } /** - * This method calls the GeoIP2 Precision: Insights service. + * This method calls the Insights service. Insights is only supported by + * the GeoIP2 web service. The GeoLite2 web service does not support it. * * @param string $ipAddress IPv4 or IPv6 address as a string. If no * address is provided, the address that the web service is called @@ -168,25 +188,27 @@ class Client implements ProviderInterface * @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 \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. */ - public function insights(string $ipAddress = 'me'): \GeoIp2\Model\Insights + public function insights(string $ipAddress = 'me'): Insights { - return $this->responseFor('insights', 'Insights', $ipAddress); + // @phpstan-ignore-next-line + return $this->responseFor('insights', Insights::class, $ipAddress); } - private function responseFor(string $endpoint, string $class, string $ipAddress) + private function responseFor(string $endpoint, string $class, string $ipAddress): Country { $path = implode('/', [self::$basePath, $endpoint, $ipAddress]); try { - $body = $this->client->get('GeoIP2 ' . $class, $path); + $service = (new \ReflectionClass($class))->getShortName(); + $body = $this->client->get('GeoIP2 ' . $service, $path); } catch (\MaxMind\Exception\IpAddressNotFoundException $ex) { throw new AddressNotFoundException( $ex->getMessage(), @@ -228,8 +250,6 @@ class Client implements ProviderInterface ); } - $class = 'GeoIp2\\Model\\' . $class; - return new $class($body, $this->locales); } } diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 7ea84b97fb8..9a6fd29783f 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -400,7 +400,7 @@ All rights reserved. maxmind/GeoIp2 GeoIP2 PHP API Library for processing of GeoIP data files. - 2.11.0 + 2.13.0 Apache 2.0 https://github.com/maxmind/GeoIP2-php