From a463af10afbcbb8a8183cdcb679d151951b5c546 Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 09:33:17 -0700
Subject: [PATCH 01/10] Drop 8.0 support. Test on 8.2.
---
.github/workflows/lint.yml | 2 +-
.github/workflows/test.yml | 2 +-
CHANGELOG.md | 2 +-
README.md | 2 +-
composer.json | 4 ++--
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 19ba7ffa..7b22bd53 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -14,7 +14,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
- php-version: 8.1
+ php-version: 8.2
- name: Checkout
uses: actions/checkout@v4
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c763ecf9..6c434809 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
- php-versions: ['8.0', '8.1']
+ php-versions: ['8.1', '8.2']
name: "PHP ${{ matrix.php-versions }} test on ${{ matrix.operating-system }}"
steps:
- name: Setup PHP
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72e83e96..fbe8f97a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@ CHANGELOG
3.0.0
-------------------
-* IMPORTANT: PHP 8.0 or greater is now required.
+* IMPORTANT: PHP 8.1 or greater is now required.
* `GeoIp2\WebService\Client` methods now throw an `InvalidArgumentException`
if an invalid IP address is passed to them. Previously, they would make
a request to the web service and throw a
diff --git a/README.md b/README.md
index f92a4162..01502e9b 100644
--- a/README.md
+++ b/README.md
@@ -430,7 +430,7 @@ to the client API, please see
## Requirements ##
-This library requires PHP 8.0 or greater.
+This library requires PHP 8.1 or greater.
This library also relies on the [MaxMind DB Reader](https://github.com/maxmind/MaxMind-DB-Reader-php).
diff --git a/composer.json b/composer.json
index c7365a43..a45a613d 100644
--- a/composer.json
+++ b/composer.json
@@ -15,12 +15,12 @@
"require": {
"maxmind-db/reader": "~1.8",
"maxmind/web-service-common": "~0.8",
- "php": ">=8.0",
+ "php": ">=8.1",
"ext-json": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
- "phpunit/phpunit": "^8.0 || ^9.0",
+ "phpunit/phpunit": "^9.0",
"squizlabs/php_codesniffer": "3.*",
"phpstan/phpstan": "*"
},
From 37774da1b82f286d485831291c086ebe59b9be5c Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Mon, 30 Oct 2023 13:05:35 -0700
Subject: [PATCH 02/10] Use readonly properties
---
CHANGELOG.md | 5 +
src/Database/Reader.php | 13 +--
src/Model/AbstractModel.php | 68 ------------
src/Model/AnonymousIp.php | 50 +++++----
src/Model/Asn.php | 29 +++--
src/Model/City.php | 74 ++++++-------
src/Model/ConnectionType.php | 25 +++--
src/Model/Country.php | 47 ++++----
src/Model/Domain.php | 25 +++--
src/Model/Isp.php | 49 ++++++---
src/Record/AbstractNamedRecord.php | 41 +++++++
src/Record/AbstractPlaceRecord.php | 60 ++--------
src/Record/AbstractRecord.php | 67 ------------
src/Record/City.php | 11 +-
src/Record/Continent.php | 28 +++--
src/Record/Country.php | 28 +++--
src/Record/Location.php | 49 ++++++---
src/Record/MaxMind.php | 21 ++--
src/Record/Postal.php | 21 +++-
src/Record/RepresentedCountry.php | 26 +++--
src/Record/Subdivision.php | 24 ++--
src/Record/Traits.php | 111 +++++++++++++------
tests/GeoIp2/Test/Model/CountryTest.php | 93 +++++++++++-----
tests/GeoIp2/Test/Model/InsightsTest.php | 134 ++++++++++++++++++-----
24 files changed, 614 insertions(+), 485 deletions(-)
delete mode 100644 src/Model/AbstractModel.php
create mode 100644 src/Record/AbstractNamedRecord.php
delete mode 100644 src/Record/AbstractRecord.php
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fbe8f97a..5f49667c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ 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
+ record classes have been removed.
+* BREAKING: The `jsonSerialize` output has changed.
* `GeoIp2\WebService\Client` methods now throw an `InvalidArgumentException`
if an invalid IP address is passed to them. Previously, they would make
a request to the web service and throw a
diff --git a/src/Database/Reader.php b/src/Database/Reader.php
index 0030e370..1570afb8 100644
--- a/src/Database/Reader.php
+++ b/src/Database/Reader.php
@@ -5,7 +5,6 @@
namespace GeoIp2\Database;
use GeoIp2\Exception\AddressNotFoundException;
-use GeoIp2\Model\AbstractModel;
use GeoIp2\Model\AnonymousIp;
use GeoIp2\Model\Asn;
use GeoIp2\Model\City;
@@ -84,7 +83,6 @@ public function __construct(
*/
public function city(string $ipAddress): City
{
- // @phpstan-ignore-next-line
return $this->modelFor(City::class, 'City', $ipAddress);
}
@@ -100,7 +98,6 @@ public function city(string $ipAddress): City
*/
public function country(string $ipAddress): Country
{
- // @phpstan-ignore-next-line
return $this->modelFor(Country::class, 'Country', $ipAddress);
}
@@ -116,7 +113,6 @@ public function country(string $ipAddress): Country
*/
public function anonymousIp(string $ipAddress): AnonymousIp
{
- // @phpstan-ignore-next-line
return $this->flatModelFor(
AnonymousIp::class,
'GeoIP2-Anonymous-IP',
@@ -136,7 +132,6 @@ public function anonymousIp(string $ipAddress): AnonymousIp
*/
public function asn(string $ipAddress): Asn
{
- // @phpstan-ignore-next-line
return $this->flatModelFor(
Asn::class,
'GeoLite2-ASN',
@@ -156,7 +151,6 @@ public function asn(string $ipAddress): Asn
*/
public function connectionType(string $ipAddress): ConnectionType
{
- // @phpstan-ignore-next-line
return $this->flatModelFor(
ConnectionType::class,
'GeoIP2-Connection-Type',
@@ -176,7 +170,6 @@ public function connectionType(string $ipAddress): ConnectionType
*/
public function domain(string $ipAddress): Domain
{
- // @phpstan-ignore-next-line
return $this->flatModelFor(
Domain::class,
'GeoIP2-Domain',
@@ -196,7 +189,6 @@ public function domain(string $ipAddress): Domain
*/
public function enterprise(string $ipAddress): Enterprise
{
- // @phpstan-ignore-next-line
return $this->modelFor(Enterprise::class, 'Enterprise', $ipAddress);
}
@@ -212,7 +204,6 @@ public function enterprise(string $ipAddress): Enterprise
*/
public function isp(string $ipAddress): Isp
{
- // @phpstan-ignore-next-line
return $this->flatModelFor(
Isp::class,
'GeoIP2-ISP',
@@ -220,7 +211,7 @@ public function isp(string $ipAddress): Isp
);
}
- private function modelFor(string $class, string $type, string $ipAddress): AbstractModel
+ private function modelFor(string $class, string $type, string $ipAddress): object
{
[$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress);
@@ -230,7 +221,7 @@ private function modelFor(string $class, string $type, string $ipAddress): Abstr
return new $class($record, $this->locales);
}
- private function flatModelFor(string $class, string $type, string $ipAddress): AbstractModel
+ private function flatModelFor(string $class, string $type, string $ipAddress): object
{
[$record, $prefixLen] = $this->getRecord($class, $type, $ipAddress);
diff --git a/src/Model/AbstractModel.php b/src/Model/AbstractModel.php
deleted file mode 100644
index f44feaeb..00000000
--- a/src/Model/AbstractModel.php
+++ /dev/null
@@ -1,68 +0,0 @@
-
- */
- protected array $raw;
-
- /**
- * @ignore
- */
- public function __construct(array $raw)
- {
- $this->raw = $raw;
- }
-
- /**
- * @ignore
- *
- * @return mixed
- */
- protected function get(string $field)
- {
- if (isset($this->raw[$field])) {
- return $this->raw[$field];
- }
- if (preg_match('/^is_/', $field)) {
- return false;
- }
-
- return null;
- }
-
- /**
- * @ignore
- *
- * @return mixed
- */
- public function __get(string $attr)
- {
- if ($attr !== 'instance' && property_exists($this, $attr)) {
- return $this->{$attr};
- }
-
- throw new \RuntimeException("Unknown attribute: $attr");
- }
-
- /**
- * @ignore
- */
- public function __isset(string $attr): bool
- {
- return $attr !== 'instance' && isset($this->{$attr});
- }
-
- public function jsonSerialize(): array
- {
- return $this->raw;
- }
-}
diff --git a/src/Model/AnonymousIp.php b/src/Model/AnonymousIp.php
index da566146..6cd9ef9d 100644
--- a/src/Model/AnonymousIp.php
+++ b/src/Model/AnonymousIp.php
@@ -29,32 +29,44 @@
* the record. In particular, this is the largest network where all of the
* fields besides $ipAddress have the same value.
*/
-class AnonymousIp extends AbstractModel
+class AnonymousIp implements \JsonSerializable
{
- protected bool $isAnonymous;
- protected bool $isAnonymousVpn;
- protected bool $isHostingProvider;
- protected bool $isPublicProxy;
- protected bool $isResidentialProxy;
- protected bool $isTorExitNode;
- protected string $ipAddress;
- protected string $network;
+ public readonly bool $isAnonymous;
+ public readonly bool $isAnonymousVpn;
+ public readonly bool $isHostingProvider;
+ public readonly bool $isPublicProxy;
+ public readonly bool $isResidentialProxy;
+ public readonly bool $isTorExitNode;
+ public readonly string $ipAddress;
+ public readonly string $network;
/**
* @ignore
*/
public function __construct(array $raw)
{
- parent::__construct($raw);
-
- $this->isAnonymous = $this->get('is_anonymous');
- $this->isAnonymousVpn = $this->get('is_anonymous_vpn');
- $this->isHostingProvider = $this->get('is_hosting_provider');
- $this->isPublicProxy = $this->get('is_public_proxy');
- $this->isResidentialProxy = $this->get('is_residential_proxy');
- $this->isTorExitNode = $this->get('is_tor_exit_node');
- $ipAddress = $this->get('ip_address');
+ $this->isAnonymous = $raw['is_anonymous'] ?? false;
+ $this->isAnonymousVpn = $raw['is_anonymous_vpn'] ?? false;
+ $this->isHostingProvider = $raw['is_hosting_provider'] ?? false;
+ $this->isPublicProxy = $raw['is_public_proxy'] ?? false;
+ $this->isResidentialProxy = $raw['is_residential_proxy'] ?? false;
+ $this->isTorExitNode = $raw['is_tor_exit_node'] ?? false;
+ $ipAddress = $raw['ip_address'];
$this->ipAddress = $ipAddress;
- $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
+ $this->network = Util::cidr($ipAddress, $raw['prefix_len']);
+ }
+
+ public function jsonSerialize(): ?array
+ {
+ return [
+ 'is_anonymous' => $this->isAnonymous,
+ 'is_anonymous_vpn' => $this->isAnonymousVpn,
+ 'is_hosting_provider' => $this->isHostingProvider,
+ 'is_public_proxy' => $this->isPublicProxy,
+ 'is_residential_proxy' => $this->isResidentialProxy,
+ 'is_tor_exit_node' => $this->isTorExitNode,
+ 'ip_address' => $this->ipAddress,
+ 'network' => $this->network,
+ ];
}
}
diff --git a/src/Model/Asn.php b/src/Model/Asn.php
index 42e9a4a2..1cb1aa11 100644
--- a/src/Model/Asn.php
+++ b/src/Model/Asn.php
@@ -20,24 +20,33 @@
* the record. In particular, this is the largest network where all of the
* fields besides $ipAddress have the same value.
*/
-class Asn extends AbstractModel
+class Asn implements \JsonSerializable
{
- protected ?int $autonomousSystemNumber;
- protected ?string $autonomousSystemOrganization;
- protected string $ipAddress;
- protected string $network;
+ public readonly ?int $autonomousSystemNumber;
+ public readonly ?string $autonomousSystemOrganization;
+ public readonly string $ipAddress;
+ public readonly string $network;
/**
* @ignore
*/
public function __construct(array $raw)
{
- parent::__construct($raw);
- $this->autonomousSystemNumber = $this->get('autonomous_system_number');
+ $this->autonomousSystemNumber = $raw['autonomous_system_number'] ?? null;
$this->autonomousSystemOrganization =
- $this->get('autonomous_system_organization');
- $ipAddress = $this->get('ip_address');
+ $raw['autonomous_system_organization'] ?? null;
+ $ipAddress = $raw['ip_address'];
$this->ipAddress = $ipAddress;
- $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
+ $this->network = Util::cidr($ipAddress, $raw['prefix_len']);
+ }
+
+ public function jsonSerialize(): ?array
+ {
+ return [
+ 'autonomous_system_number' => $this->autonomousSystemNumber,
+ 'autonomous_system_organization' => $this->autonomousSystemOrganization,
+ 'ip_address' => $this->ipAddress,
+ 'network' => $this->network,
+ ];
}
}
diff --git a/src/Model/City.php b/src/Model/City.php
index 19f2b2c4..758ae1e5 100644
--- a/src/Model/City.php
+++ b/src/Model/City.php
@@ -34,24 +34,29 @@ class City extends Country
/**
* @ignore
*/
- protected \GeoIp2\Record\City $city;
+ public readonly \GeoIp2\Record\City $city;
/**
* @ignore
*/
- protected \GeoIp2\Record\Location $location;
+ public readonly \GeoIp2\Record\Location $location;
/**
* @ignore
*/
- protected \GeoIp2\Record\Postal $postal;
+ public readonly \GeoIp2\Record\Subdivision $mostSpecificSubdivision;
+
+ /**
+ * @ignore
+ */
+ public readonly \GeoIp2\Record\Postal $postal;
/**
* @ignore
*
* @var array<\GeoIp2\Record\Subdivision>
*/
- protected array $subdivisions = [];
+ public readonly array $subdivisions;
/**
* @ignore
@@ -60,58 +65,45 @@ public function __construct(array $raw, array $locales = ['en'])
{
parent::__construct($raw, $locales);
- $this->city = new \GeoIp2\Record\City($this->get('city'), $locales);
- $this->location = new \GeoIp2\Record\Location($this->get('location'));
- $this->postal = new \GeoIp2\Record\Postal($this->get('postal'));
-
- $this->createSubdivisions($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'] ?? []);
- private function createSubdivisions(array $raw, array $locales): void
- {
if (!isset($raw['subdivisions'])) {
+ $this->subdivisions = [];
+ $this->mostSpecificSubdivision =
+ new \GeoIp2\Record\Subdivision([], $locales);
+
return;
}
+ $subdivisions = [];
foreach ($raw['subdivisions'] as $sub) {
- $this->subdivisions[] =
+ $subdivisions[] =
new \GeoIp2\Record\Subdivision($sub, $locales)
;
}
+
+ // Not using end as we don't want to modify internal pointer.
+ $this->mostSpecificSubdivision =
+ $subdivisions[\count($subdivisions) - 1];
+ $this->subdivisions = $subdivisions;
}
- /**
- * @ignore
- *
- * @return mixed
- */
- public function __get(string $attr)
+ public function jsonSerialize(): ?array
{
- if ($attr === 'mostSpecificSubdivision') {
- return $this->{$attr}();
- }
+ $js = parent::jsonSerialize();
- return parent::__get($attr);
- }
+ $js['city'] = $this->city->jsonSerialize();
+ $js['location'] = $this->location->jsonSerialize();
+ $js['postal'] = $this->postal->jsonSerialize();
- /**
- * @ignore
- */
- public function __isset(string $attr): bool
- {
- if ($attr === 'mostSpecificSubdivision') {
- // We always return a mostSpecificSubdivision, even if it is the
- // empty subdivision
- return true;
+ $subdivisions = [];
+ foreach ($this->subdivisions as $sub) {
+ $subdivisions[] = $sub->jsonSerialize();
}
+ $js['subdivisions'] = $subdivisions;
- return parent::__isset($attr);
- }
-
- private function mostSpecificSubdivision(): \GeoIp2\Record\Subdivision
- {
- return empty($this->subdivisions) ?
- new \GeoIp2\Record\Subdivision([], $this->locales) :
- end($this->subdivisions);
+ return $js;
}
}
diff --git a/src/Model/ConnectionType.php b/src/Model/ConnectionType.php
index eba9b4d3..952835c1 100644
--- a/src/Model/ConnectionType.php
+++ b/src/Model/ConnectionType.php
@@ -18,22 +18,29 @@
* the record. In particular, this is the largest network where all of the
* fields besides $ipAddress have the same value.
*/
-class ConnectionType extends AbstractModel
+class ConnectionType implements \JsonSerializable
{
- protected ?string $connectionType;
- protected string $ipAddress;
- protected string $network;
+ public readonly ?string $connectionType;
+ public readonly string $ipAddress;
+ public readonly string $network;
/**
* @ignore
*/
public function __construct(array $raw)
{
- parent::__construct($raw);
-
- $this->connectionType = $this->get('connection_type');
- $ipAddress = $this->get('ip_address');
+ $this->connectionType = $raw['connection_type'] ?? null;
+ $ipAddress = $raw['ip_address'];
$this->ipAddress = $ipAddress;
- $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
+ $this->network = Util::cidr($ipAddress, $raw['prefix_len']);
+ }
+
+ public function jsonSerialize(): ?array
+ {
+ return [
+ 'connection_type' => $this->connectionType,
+ 'ip_address' => $this->ipAddress,
+ 'network' => $this->network,
+ ];
}
}
diff --git a/src/Model/Country.php b/src/Model/Country.php
index b026b1fe..95e459d7 100644
--- a/src/Model/Country.php
+++ b/src/Model/Country.php
@@ -26,49 +26,50 @@
* 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
+class Country implements \JsonSerializable
{
- protected \GeoIp2\Record\Continent $continent;
- protected \GeoIp2\Record\Country $country;
-
- /**
- * @var array
- */
- protected array $locales;
-
- protected \GeoIp2\Record\MaxMind $maxmind;
- protected \GeoIp2\Record\Country $registeredCountry;
- protected \GeoIp2\Record\RepresentedCountry $representedCountry;
- protected \GeoIp2\Record\Traits $traits;
+ public readonly \GeoIp2\Record\Continent $continent;
+ public readonly \GeoIp2\Record\Country $country;
+ public readonly \GeoIp2\Record\MaxMind $maxmind;
+ public readonly \GeoIp2\Record\Country $registeredCountry;
+ public readonly \GeoIp2\Record\RepresentedCountry $representedCountry;
+ public readonly \GeoIp2\Record\Traits $traits;
/**
* @ignore
*/
public function __construct(array $raw, array $locales = ['en'])
{
- parent::__construct($raw);
-
$this->continent = new \GeoIp2\Record\Continent(
- $this->get('continent'),
+ $raw['continent'] ?? [],
$locales
);
$this->country = new \GeoIp2\Record\Country(
- $this->get('country'),
+ $raw['country'] ?? [],
$locales
);
- $this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind'));
+ $this->maxmind = new \GeoIp2\Record\MaxMind($raw['maxmind'] ?? []);
$this->registeredCountry = new \GeoIp2\Record\Country(
- $this->get('registered_country'),
+ $raw['registered_country'] ?? [],
$locales
);
$this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
- $this->get('represented_country'),
+ $raw['represented_country'] ?? [],
$locales
);
- $this->traits = new \GeoIp2\Record\Traits($this->get('traits'));
+ $this->traits = new \GeoIp2\Record\Traits($raw['traits'] ?? []);
+ }
- $this->locales = $locales;
+ public function jsonSerialize(): ?array
+ {
+ return [
+ 'continent' => $this->continent->jsonSerialize(),
+ 'country' => $this->country->jsonSerialize(),
+ 'maxmind' => $this->maxmind->jsonSerialize(),
+ 'registered_country' => $this->registeredCountry->jsonSerialize(),
+ 'represented_country' => $this->representedCountry->jsonSerialize(),
+ 'traits' => $this->traits->jsonSerialize(),
+ ];
}
}
diff --git a/src/Model/Domain.php b/src/Model/Domain.php
index 95b8dcb8..4f04e7a1 100644
--- a/src/Model/Domain.php
+++ b/src/Model/Domain.php
@@ -18,22 +18,29 @@
* the record. In particular, this is the largest network where all of the
* fields besides $ipAddress have the same value.
*/
-class Domain extends AbstractModel
+class Domain implements \JsonSerializable
{
- protected ?string $domain;
- protected string $ipAddress;
- protected string $network;
+ public readonly ?string $domain;
+ public readonly string $ipAddress;
+ public readonly string $network;
/**
* @ignore
*/
public function __construct(array $raw)
{
- parent::__construct($raw);
-
- $this->domain = $this->get('domain');
- $ipAddress = $this->get('ip_address');
+ $this->domain = $raw['domain'] ?? null;
+ $ipAddress = $raw['ip_address'];
$this->ipAddress = $ipAddress;
- $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
+ $this->network = Util::cidr($ipAddress, $raw['prefix_len']);
+ }
+
+ public function jsonSerialize(): ?array
+ {
+ return [
+ 'domain' => $this->domain,
+ 'ip_address' => $this->ipAddress,
+ 'network' => $this->network,
+ ];
}
}
diff --git a/src/Model/Isp.php b/src/Model/Isp.php
index 992ea2a6..afa480f0 100644
--- a/src/Model/Isp.php
+++ b/src/Model/Isp.php
@@ -30,33 +30,46 @@
* the record. In particular, this is the largest network where all of the
* fields besides $ipAddress have the same value.
*/
-class Isp extends AbstractModel
+class Isp implements \JsonSerializable
{
- protected ?int $autonomousSystemNumber;
- protected ?string $autonomousSystemOrganization;
- protected ?string $isp;
- protected ?string $mobileCountryCode;
- protected ?string $mobileNetworkCode;
- protected ?string $organization;
- protected string $ipAddress;
- protected string $network;
+ public readonly ?int $autonomousSystemNumber;
+ public readonly ?string $autonomousSystemOrganization;
+ public readonly ?string $isp;
+ public readonly ?string $mobileCountryCode;
+ public readonly ?string $mobileNetworkCode;
+ public readonly ?string $organization;
+ public readonly string $ipAddress;
+ public readonly string $network;
/**
* @ignore
*/
public function __construct(array $raw)
{
- parent::__construct($raw);
- $this->autonomousSystemNumber = $this->get('autonomous_system_number');
+ $this->autonomousSystemNumber = $raw['autonomous_system_number'] ?? null;
$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');
+ $raw['autonomous_system_organization'] ?? null;
+ $this->isp = $raw['isp'] ?? null;
+ $this->mobileCountryCode = $raw['mobile_country_code'] ?? null;
+ $this->mobileNetworkCode = $raw['mobile_network_code'] ?? null;
+ $this->organization = $raw['organization'] ?? null;
- $ipAddress = $this->get('ip_address');
+ $ipAddress = $raw['ip_address'];
$this->ipAddress = $ipAddress;
- $this->network = Util::cidr($ipAddress, $this->get('prefix_len'));
+ $this->network = Util::cidr($ipAddress, $raw['prefix_len']);
+ }
+
+ public function jsonSerialize(): ?array
+ {
+ return [
+ 'autonomous_system_number' => $this->autonomousSystemNumber,
+ 'autonomous_system_organization' => $this->autonomousSystemOrganization,
+ 'isp' => $this->isp,
+ 'mobile_country_code' => $this->mobileCountryCode,
+ 'mobile_network_code' => $this->mobileNetworkCode,
+ 'organization' => $this->organization,
+ 'ip_address' => $this->ipAddress,
+ 'network' => $this->network,
+ ];
}
}
diff --git a/src/Record/AbstractNamedRecord.php b/src/Record/AbstractNamedRecord.php
new file mode 100644
index 00000000..79a49277
--- /dev/null
+++ b/src/Record/AbstractNamedRecord.php
@@ -0,0 +1,41 @@
+names = $record['names'] ?? [];
+
+ foreach ($locales as $locale) {
+ if (isset($this->names[$locale])) {
+ $this->name = $this->names[$locale];
+
+ return;
+ }
+ }
+ $this->name = null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ $js = [];
+ if ($this->name !== null) {
+ $js['name'] = $this->name;
+ }
+ if (!empty($this->names)) {
+ $js['names'] = $this->names;
+ }
+
+ return $js;
+ }
+}
diff --git a/src/Record/AbstractPlaceRecord.php b/src/Record/AbstractPlaceRecord.php
index 16329a3d..e01ad88c 100644
--- a/src/Record/AbstractPlaceRecord.php
+++ b/src/Record/AbstractPlaceRecord.php
@@ -4,64 +4,28 @@
namespace GeoIp2\Record;
-abstract class AbstractPlaceRecord extends AbstractRecord
+abstract class AbstractPlaceRecord extends AbstractNamedRecord
{
- /**
- * @var array
- */
- private array $locales;
-
- /**
- * @ignore
- */
- public function __construct(?array $record, array $locales = ['en'])
- {
- $this->locales = $locales;
- parent::__construct($record);
- }
+ public readonly ?int $confidence;
+ public readonly ?int $geonameId;
/**
* @ignore
- *
- * @return mixed
*/
- public function __get(string $attr)
- {
- if ($attr === 'name') {
- return $this->name();
- }
-
- return parent::__get($attr);
- }
-
- /**
- * @ignore
- */
- public function __isset(string $attr): bool
- {
- if ($attr === 'name') {
- return $this->firstSetNameLocale() !== null;
- }
-
- return parent::__isset($attr);
- }
-
- private function name(): ?string
+ public function __construct(array $record, array $locales = ['en'])
{
- $locale = $this->firstSetNameLocale();
+ parent::__construct($record, $locales);
- // @phpstan-ignore-next-line
- return $locale === null ? null : $this->names[$locale];
+ $this->confidence = $record['confidence'] ?? null;
+ $this->geonameId = $record['geoname_id'] ?? null;
}
- private function firstSetNameLocale(): ?string
+ public function jsonSerialize(): array
{
- foreach ($this->locales as $locale) {
- if (isset($this->names[$locale])) {
- return $locale;
- }
- }
+ $js = parent::jsonSerialize();
+ $js['confidence'] = $this->confidence;
+ $js['geoname_id'] = $this->geonameId;
- return null;
+ return $js;
}
}
diff --git a/src/Record/AbstractRecord.php b/src/Record/AbstractRecord.php
deleted file mode 100644
index 1e36fd0f..00000000
--- a/src/Record/AbstractRecord.php
+++ /dev/null
@@ -1,67 +0,0 @@
-
- */
- private array $record;
-
- /**
- * @ignore
- */
- public function __construct(?array $record)
- {
- $this->record = isset($record) ? $record : [];
- }
-
- /**
- * @ignore
- *
- * @return mixed
- */
- public function __get(string $attr)
- {
- // XXX - kind of ugly but greatly reduces boilerplate code
- $key = $this->attributeToKey($attr);
-
- if ($this->__isset($attr)) {
- return $this->record[$key];
- }
- 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)]);
- }
-
- private function attributeToKey(string $attr): string
- {
- return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
- }
-
- private function validAttribute(string $attr): bool
- {
- // @phpstan-ignore-next-line
- return \in_array($attr, $this->validAttributes, true);
- }
-
- public function jsonSerialize(): ?array
- {
- return $this->record;
- }
-}
diff --git a/src/Record/City.php b/src/Record/City.php
index f65d96b0..cf27fc84 100644
--- a/src/Record/City.php
+++ b/src/Record/City.php
@@ -22,12 +22,5 @@
* and the values are names. This attribute is returned by all location
* services and databases.
*/
-class City extends AbstractPlaceRecord
-{
- /**
- * @ignore
- *
- * @var array
- */
- protected array $validAttributes = ['confidence', 'geonameId', 'names'];
-}
+// phpcs:disable
+class City extends AbstractPlaceRecord {}
diff --git a/src/Record/Continent.php b/src/Record/Continent.php
index a3e28722..30fc37f9 100644
--- a/src/Record/Continent.php
+++ b/src/Record/Continent.php
@@ -21,16 +21,28 @@
* and the values are names. This attribute is returned by all location
* services and databases.
*/
-class Continent extends AbstractPlaceRecord
+class Continent extends AbstractNamedRecord
{
+ public readonly ?string $code;
+ public readonly ?int $geonameId;
+
/**
* @ignore
- *
- * @var array
*/
- protected array $validAttributes = [
- 'code',
- 'geonameId',
- 'names',
- ];
+ public function __construct(array $record, array $locales = ['en'])
+ {
+ parent::__construct($record, $locales);
+
+ $this->code = $record['code'] ?? null;
+ $this->geonameId = $record['geoname_id'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ $js = parent::jsonSerialize();
+ $js['code'] = $this->code;
+ $js['geoname_id'] = $this->geonameId;
+
+ return $js;
+ }
}
diff --git a/src/Record/Country.php b/src/Record/Country.php
index d1f239bb..d6e4cbb2 100644
--- a/src/Record/Country.php
+++ b/src/Record/Country.php
@@ -29,16 +29,26 @@
*/
class Country extends AbstractPlaceRecord
{
+ public readonly bool $isInEuropeanUnion;
+ public readonly ?string $isoCode;
+
/**
* @ignore
- *
- * @var array
*/
- protected array $validAttributes = [
- 'confidence',
- 'geonameId',
- 'isInEuropeanUnion',
- 'isoCode',
- 'names',
- ];
+ public function __construct(array $record, array $locales = ['en'])
+ {
+ parent::__construct($record, $locales);
+
+ $this->isInEuropeanUnion = $record['is_in_european_union'] ?? false;
+ $this->isoCode = $record['iso_code'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ $js = parent::jsonSerialize();
+ $js['is_in_european_union'] = $this->isInEuropeanUnion;
+ $js['iso_code'] = $this->isoCode;
+
+ return $js;
+ }
}
diff --git a/src/Record/Location.php b/src/Record/Location.php
index 202fffa6..369898f7 100644
--- a/src/Record/Location.php
+++ b/src/Record/Location.php
@@ -35,22 +35,37 @@
* specified by the IANA Time Zone Database, e.g., "America/New_York". See
* https://www.iana.org/time-zones.
*/
-class Location extends AbstractRecord
+class Location implements \JsonSerializable
{
- /**
- * @ignore
- *
- * @var array
- */
- protected array $validAttributes = [
- 'averageIncome',
- 'accuracyRadius',
- 'latitude',
- 'longitude',
- 'metroCode',
- 'populationDensity',
- 'postalCode',
- 'postalConfidence',
- 'timeZone',
- ];
+ public readonly ?int $averageIncome;
+ public readonly ?int $accuracyRadius;
+ public readonly ?float $latitude;
+ public readonly ?float $longitude;
+ public readonly ?int $metroCode;
+ public readonly ?int $populationDensity;
+ public readonly ?string $timeZone;
+
+ public function __construct(array $record)
+ {
+ $this->averageIncome = $record['average_income'] ?? null;
+ $this->accuracyRadius = $record['accuracy_radius'] ?? null;
+ $this->latitude = $record['latitude'] ?? null;
+ $this->longitude = $record['longitude'] ?? null;
+ $this->metroCode = $record['metro_code'] ?? null;
+ $this->populationDensity = $record['population_density'] ?? null;
+ $this->timeZone = $record['time_zone'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ return [
+ 'average_income' => $this->averageIncome,
+ 'accuracy_radius' => $this->accuracyRadius,
+ 'latitude' => $this->latitude,
+ 'longitude' => $this->longitude,
+ 'metro_code' => $this->metroCode,
+ 'population_density' => $this->populationDensity,
+ 'time_zone' => $this->timeZone,
+ ];
+ }
}
diff --git a/src/Record/MaxMind.php b/src/Record/MaxMind.php
index 4e599675..2be550b8 100644
--- a/src/Record/MaxMind.php
+++ b/src/Record/MaxMind.php
@@ -12,12 +12,19 @@
* @property-read int|null $queriesRemaining The number of remaining queries you
* have for the service you are calling.
*/
-class MaxMind extends AbstractRecord
+class MaxMind implements \JsonSerializable
{
- /**
- * @ignore
- *
- * @var array
- */
- protected array $validAttributes = ['queriesRemaining'];
+ public readonly ?int $queriesRemaining;
+
+ public function __construct(array $record)
+ {
+ $this->queriesRemaining = $record['queries_remaining'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ return [
+ 'queries_remaining' => $this->queriesRemaining,
+ ];
+ }
}
diff --git a/src/Record/Postal.php b/src/Record/Postal.php
index 2ac67e30..05481b9d 100644
--- a/src/Record/Postal.php
+++ b/src/Record/Postal.php
@@ -19,12 +19,25 @@
* available from the Insights service and the GeoIP2 Enterprise
* database.
*/
-class Postal extends AbstractRecord
+class Postal implements \JsonSerializable
{
+ public readonly ?string $code;
+ public readonly ?int $confidence;
+
/**
* @ignore
- *
- * @var array
*/
- protected array $validAttributes = ['code', 'confidence'];
+ public function __construct(array $record)
+ {
+ $this->code = $record['code'] ?? null;
+ $this->confidence = $record['confidence'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ return [
+ 'code' => $this->code,
+ 'confidence' => $this->confidence,
+ ];
+ }
}
diff --git a/src/Record/RepresentedCountry.php b/src/Record/RepresentedCountry.php
index 717fd852..6e857326 100644
--- a/src/Record/RepresentedCountry.php
+++ b/src/Record/RepresentedCountry.php
@@ -17,17 +17,23 @@
*/
class RepresentedCountry extends Country
{
+ public readonly ?string $type;
+
/**
* @ignore
- *
- * @var array
*/
- protected array $validAttributes = [
- 'confidence',
- 'geonameId',
- 'isInEuropeanUnion',
- 'isoCode',
- 'names',
- 'type',
- ];
+ public function __construct(array $record, array $locales = ['en'])
+ {
+ parent::__construct($record, $locales);
+
+ $this->type = $record['type'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ $js = parent::jsonSerialize();
+ $js['type'] = $this->type;
+
+ return $js;
+ }
}
diff --git a/src/Record/Subdivision.php b/src/Record/Subdivision.php
index ac8cd285..7ae7f3c7 100644
--- a/src/Record/Subdivision.php
+++ b/src/Record/Subdivision.php
@@ -30,15 +30,23 @@
*/
class Subdivision extends AbstractPlaceRecord
{
+ public readonly ?string $isoCode;
+
/**
* @ignore
- *
- * @var array
*/
- protected array $validAttributes = [
- 'confidence',
- 'geonameId',
- 'isoCode',
- 'names',
- ];
+ public function __construct(array $record, array $locales = ['en'])
+ {
+ parent::__construct($record, $locales);
+
+ $this->isoCode = $record['iso_code'] ?? null;
+ }
+
+ public function jsonSerialize(): array
+ {
+ $js = parent::jsonSerialize();
+ $js['iso_code'] = $this->isoCode;
+
+ return $js;
+ }
}
diff --git a/src/Record/Traits.php b/src/Record/Traits.php
index f831f323..0e72ccee 100644
--- a/src/Record/Traits.php
+++ b/src/Record/Traits.php
@@ -116,44 +116,87 @@
* GeoIP2 Enterprise database.
*
*/
-class Traits extends AbstractRecord
+class Traits implements \JsonSerializable
{
- /**
- * @ignore
- *
- * @var array
- */
- protected array $validAttributes = [
- 'autonomousSystemNumber',
- 'autonomousSystemOrganization',
- 'connectionType',
- 'domain',
- 'ipAddress',
- 'isAnonymous',
- 'isAnonymousProxy',
- 'isAnonymousVpn',
- 'isHostingProvider',
- 'isLegitimateProxy',
- 'isp',
- 'isPublicProxy',
- 'isResidentialProxy',
- 'isSatelliteProvider',
- 'isTorExitNode',
- 'mobileCountryCode',
- 'mobileNetworkCode',
- 'network',
- 'organization',
- 'staticIpScore',
- 'userCount',
- 'userType',
- ];
+ public readonly ?int $autonomousSystemNumber;
+ public readonly ?string $autonomousSystemOrganization;
+ public readonly ?string $connectionType;
+ public readonly ?string $domain;
+ public readonly string $ipAddress;
+ public readonly bool $isAnonymous;
+ public readonly bool $isAnonymousProxy;
+ public readonly bool $isAnonymousVpn;
+ public readonly bool $isHostingProvider;
+ public readonly bool $isLegitimateProxy;
+ public readonly ?string $isp;
+ public readonly bool $isPublicProxy;
+ public readonly bool $isResidentialProxy;
+ public readonly bool $isSatelliteProvider;
+ public readonly bool $isTorExitNode;
+ public readonly ?string $mobileCountryCode;
+ public readonly ?string $mobileNetworkCode;
+ public readonly string $network;
+ public readonly ?string $organization;
+ public readonly ?float $staticIpScore;
+ public readonly ?int $userCount;
+ public readonly ?string $userType;
- public function __construct(?array $record)
+ public function __construct(array $record)
{
- if (!isset($record['network']) && isset($record['ip_address'], $record['prefix_len'])) {
- $record['network'] = Util::cidr($record['ip_address'], $record['prefix_len']);
+ $this->autonomousSystemNumber = $record['autonomous_system_number'] ?? null;
+ $this->autonomousSystemOrganization = $record['autonomous_system_organization'] ?? null;
+ $this->connectionType = $record['connection_type'] ?? null;
+ $this->domain = $record['domain'] ?? null;
+ $this->ipAddress = $record['ip_address'] ?? null;
+ $this->isAnonymous = $record['is_anonymous'] ?? false;
+ $this->isAnonymousProxy = $record['is_anonymous_proxy'] ?? false;
+ $this->isAnonymousVpn = $record['is_anonymous_vpn'] ?? false;
+ $this->isHostingProvider = $record['is_hosting_provider'] ?? false;
+ $this->isLegitimateProxy = $record['is_legitimate_proxy'] ?? false;
+ $this->isp = $record['isp'] ?? null;
+ $this->isPublicProxy = $record['is_public_proxy'] ?? false;
+ $this->isResidentialProxy = $record['is_residential_proxy'] ?? false;
+ $this->isSatelliteProvider = $record['is_satellite_provider'] ?? false;
+ $this->isTorExitNode = $record['is_tor_exit_node'] ?? false;
+ $this->mobileCountryCode = $record['mobile_country_code'] ?? null;
+ $this->mobileNetworkCode = $record['mobile_network_code'] ?? null;
+ $this->organization = $record['organization'] ?? null;
+ $this->staticIpScore = $record['static_ip_score'] ?? null;
+ $this->userCount = $record['user_count'] ?? null;
+ $this->userType = $record['user_type'] ?? null;
+
+ if (isset($record['network'])) {
+ $this->network = $record['network'];
+ } else {
+ $this->network = Util::cidr($this->ipAddress, $record['prefix_len'] ?? 0);
}
+ }
- parent::__construct($record);
+ public function jsonSerialize(): array
+ {
+ return [
+ 'autonomous_system_number' => $this->autonomousSystemNumber,
+ 'autonomous_system_organization' => $this->autonomousSystemOrganization,
+ 'connection_type' => $this->connectionType,
+ 'domain' => $this->domain,
+ 'ip_address' => $this->ipAddress,
+ 'is_anonymous' => $this->isAnonymous,
+ 'is_anonymous_proxy' => $this->isAnonymousProxy,
+ 'is_anonymous_vpn' => $this->isAnonymousVpn,
+ 'is_hosting_provider' => $this->isHostingProvider,
+ 'is_legitimate_proxy' => $this->isLegitimateProxy,
+ 'is_public_proxy' => $this->isPublicProxy,
+ 'is_residential_proxy' => $this->isResidentialProxy,
+ 'is_satellite_provider' => $this->isSatelliteProvider,
+ 'is_tor_exit_node' => $this->isTorExitNode,
+ 'isp' => $this->isp,
+ 'mobile_country_code' => $this->mobileCountryCode,
+ 'mobile_network_code' => $this->mobileNetworkCode,
+ 'network' => $this->network,
+ 'organization' => $this->organization,
+ 'static_ip_score' => $this->staticIpScore,
+ 'user_count' => $this->userCount,
+ 'user_type' => $this->userType,
+ ];
}
}
diff --git a/tests/GeoIp2/Test/Model/CountryTest.php b/tests/GeoIp2/Test/Model/CountryTest.php
index 14fd5cd2..41e22de2 100644
--- a/tests/GeoIp2/Test/Model/CountryTest.php
+++ b/tests/GeoIp2/Test/Model/CountryTest.php
@@ -171,24 +171,79 @@ public function testValues(): void
"traits $meth returns 0 by default"
);
}
-
- $this->assertSame(
- $this->raw,
- $this->model->raw,
- 'raw method returns raw input'
- );
}
public function testJsonSerialize(): void
{
+ $js =
+ [
+ 'continent' => [
+ 'name' => 'North America',
+ 'names' => ['en' => 'North America'],
+ 'code' => 'NA',
+ 'geoname_id' => 42,
+ ],
+ 'country' => [
+ 'name' => 'United States of America',
+ 'names' => ['en' => 'United States of America'],
+ 'confidence' => null,
+ 'geoname_id' => 1,
+ 'is_in_european_union' => false,
+ 'iso_code' => 'US',
+ ],
+ 'maxmind' => [
+ 'queries_remaining' => null,
+ ],
+ 'registered_country' => [
+ 'name' => 'Germany',
+ 'names' => ['en' => 'Germany'],
+ 'confidence' => null,
+ 'geoname_id' => 2,
+ 'is_in_european_union' => true,
+ 'iso_code' => 'DE',
+ ],
+ 'represented_country' => [
+ 'name' => null,
+ 'names' => [],
+ 'confidence' => null,
+ 'geoname_id' => null,
+ 'is_in_european_union' => false,
+ 'iso_code' => null,
+ 'type' => null,
+ ],
+ 'traits' => [
+ 'autonomous_system_number' => null,
+ 'autonomous_system_organization' => null,
+ 'connection_type' => null,
+ 'domain' => null,
+ 'ip_address' => '1.2.3.4',
+ 'is_anonymous' => false,
+ 'is_anonymous_proxy' => false,
+ 'is_anonymous_vpn' => false,
+ 'is_hosting_provider' => false,
+ 'is_legitimate_proxy' => false,
+ 'is_public_proxy' => false,
+ 'is_residential_proxy' => false,
+ 'is_satellite_provider' => false,
+ 'is_tor_exit_node' => false,
+ 'isp' => null,
+ 'mobile_country_code' => null,
+ 'mobile_network_code' => null,
+ 'network' => '1.2.3.0/24',
+ 'organization' => null,
+ 'static_ip_score' => null,
+ 'user_count' => null,
+ 'user_type' => null,
+ ],
+ ];
$this->assertSame(
- $this->raw,
+ $js,
$this->model->jsonSerialize(),
'jsonSerialize returns initial array'
);
$this->assertSame(
- $this->raw['country'],
+ $js['country'],
$this->model->country->jsonSerialize(),
'jsonSerialize returns initial array for the record'
);
@@ -198,13 +253,13 @@ public function testJsonSerialize(): void
}
$this->assertSame(
- json_encode($this->raw),
+ json_encode($js),
json_encode($this->model),
'json_encode can be called on the model object directly'
);
$this->assertSame(
- json_encode($this->raw['country']),
+ json_encode($js['country']),
json_encode($this->model->country),
'json_encode can be called on the record object directly'
);
@@ -228,22 +283,4 @@ public function testIsSet(): void
'unknown trait is not set'
);
}
-
- public function testUnknownRecord(): void
- {
- $this->expectException(\RuntimeException::class);
- $this->expectExceptionMessage('Unknown attribute');
-
- // @phpstan-ignore-next-line
- $this->model->unknownRecord;
- }
-
- public function testUnknownTrait(): void
- {
- $this->expectException(\RuntimeException::class);
- $this->expectExceptionMessage('Unknown attribute');
-
- // @phpstan-ignore-next-line
- $this->model->traits->unknown;
- }
}
diff --git a/tests/GeoIp2/Test/Model/InsightsTest.php b/tests/GeoIp2/Test/Model/InsightsTest.php
index e18086af..c4252779 100644
--- a/tests/GeoIp2/Test/Model/InsightsTest.php
+++ b/tests/GeoIp2/Test/Model/InsightsTest.php
@@ -40,22 +40,27 @@ public function testFull(): void
'longitude' => 93.2636,
'metro_code' => 765,
'population_density' => 1341,
- 'postal_code' => '55401',
- 'postal_confidence' => 33,
'time_zone' => 'America/Chicago',
],
'maxmind' => [
'queries_remaining' => 22,
],
+ 'postal' => [
+ 'code' => '55401',
+ 'confidence' => 33,
+ ],
'registered_country' => [
+ 'confidence' => null,
'geoname_id' => 2,
'iso_code' => 'CA',
'names' => ['en' => 'Canada'],
],
'represented_country' => [
+ 'confidence' => null,
'geoname_id' => 3,
'iso_code' => 'GB',
'names' => ['en' => 'United Kingdom'],
+ 'type' => 'military',
],
'subdivisions' => [
[
@@ -72,8 +77,10 @@ public function testFull(): void
'domain' => 'example.com',
'ip_address' => '1.2.3.4',
'is_anonymous' => true,
+ 'is_anonymous_proxy' => true,
'is_anonymous_vpn' => true,
'is_hosting_provider' => true,
+ 'is_legitimate_proxy' => true,
'is_public_proxy' => true,
'is_residential_proxy' => true,
'is_satellite_provider' => true,
@@ -81,6 +88,7 @@ public function testFull(): void
'isp' => 'Comcast',
'mobile_country_code' => '310',
'mobile_network_code' => '004',
+ 'network' => '1.2.3.0/24',
'organization' => 'Blorg',
'static_ip_score' => 1.3,
'user_count' => 2,
@@ -191,9 +199,9 @@ public function testFull(): void
'$model->traits->isTorExitNode is true'
);
- $this->assertFalse(
+ $this->assertTrue(
$model->traits->isAnonymousProxy,
- '$model->traits->isAnonymousProxy is false'
+ '$model->traits->isAnonymousProxy is true'
);
$this->assertSame(
@@ -220,17 +228,104 @@ public function testFull(): void
'queriesRemaining is correct'
);
- $this->assertSame(
- $raw,
- $model->raw,
- 'raw method returns raw input'
- );
-
$this->assertSame(
2,
$model->traits->userCount,
'userCount is correct'
);
+
+ $this->assertSame(
+ [
+ 'continent' => [
+ 'name' => 'North America',
+ 'names' => ['en' => 'North America'],
+ 'code' => 'NA',
+ 'geoname_id' => 42,
+ ],
+ 'country' => [
+ 'name' => 'United States of America',
+ 'names' => ['en' => 'United States of America'],
+ 'confidence' => 99,
+ 'geoname_id' => 1,
+ 'is_in_european_union' => false,
+ 'iso_code' => 'US',
+ ],
+ 'maxmind' => [
+ 'queries_remaining' => 22,
+ ],
+ 'registered_country' => [
+ 'name' => 'Canada',
+ 'names' => ['en' => 'Canada'],
+ 'confidence' => null,
+ 'geoname_id' => 2,
+ 'is_in_european_union' => false,
+ 'iso_code' => 'CA',
+ ],
+ 'represented_country' => [
+ 'name' => 'United Kingdom',
+ 'names' => ['en' => 'United Kingdom'],
+ 'confidence' => null,
+ 'geoname_id' => 3,
+ 'is_in_european_union' => false,
+ 'iso_code' => 'GB',
+ 'type' => 'military',
+ ],
+ 'traits' => [
+ 'autonomous_system_number' => 1234,
+ 'autonomous_system_organization' => 'AS Organization',
+ 'connection_type' => 'Cable/DSL',
+ 'domain' => 'example.com',
+ 'ip_address' => '1.2.3.4',
+ 'is_anonymous' => true,
+ 'is_anonymous_proxy' => true,
+ 'is_anonymous_vpn' => true,
+ 'is_hosting_provider' => true,
+ 'is_legitimate_proxy' => true,
+ 'is_public_proxy' => true,
+ 'is_residential_proxy' => true,
+ 'is_satellite_provider' => true,
+ 'is_tor_exit_node' => true,
+ 'isp' => 'Comcast',
+ 'mobile_country_code' => '310',
+ 'mobile_network_code' => '004',
+ 'network' => '1.2.3.0/24',
+ 'organization' => 'Blorg',
+ 'static_ip_score' => 1.3,
+ 'user_count' => 2,
+ 'user_type' => 'college',
+ ],
+ 'city' => [
+ 'name' => 'Minneapolis',
+ 'names' => ['en' => 'Minneapolis'],
+ 'confidence' => 76,
+ 'geoname_id' => 9876,
+ ],
+ 'location' => [
+ 'average_income' => 24626,
+ 'accuracy_radius' => 1500,
+ 'latitude' => 44.98,
+ 'longitude' => 93.2636,
+ 'metro_code' => 765,
+ 'population_density' => 1341,
+ 'time_zone' => 'America/Chicago',
+ ],
+ 'postal' => [
+ 'code' => '55401',
+ 'confidence' => 33,
+ ],
+ 'subdivisions' => [
+ [
+ 'name' => 'Minnesota',
+ 'names' => ['en' => 'Minnesota'],
+ 'confidence' => 88,
+ 'geoname_id' => 574635,
+ 'iso_code' => 'MN',
+ ],
+ ],
+ ],
+ $model->jsonSerialize(),
+ 'jsonSerialize returns initial array'
+ );
}
public function testEmptyObjects(): void
@@ -293,22 +388,11 @@ public function testEmptyObjects(): void
'$model->mostSpecificSubdivision'
);
- $this->assertTrue(
- isset($model->mostSpecificSubdivision),
- 'mostSpecificSubdivision is set'
- );
-
$this->assertInstanceOf(
'GeoIp2\Record\Traits',
$model->traits,
'$model->traits'
);
-
- $this->assertSame(
- $raw,
- $model->raw,
- 'raw method returns raw input with no added empty values'
- );
}
public function testUnknown(): void
@@ -332,17 +416,11 @@ public function testUnknown(): void
$model,
'no exception when Insights model gets raw data with unknown keys'
);
-
- $this->assertSame(
- $raw,
- $model->raw,
- 'raw method returns raw input'
- );
}
public function testMostSpecificSubdivisionWithNoSubdivisions(): void
{
- $model = new Insights([], ['en']);
+ $model = new Insights(['traits' => ['ip_address' => '1.1.1.1']], ['en']);
$this->assertTrue(
isset($model->mostSpecificSubdivision),
From 43370560c25a995543dff6e333fe961d41a90f9d Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Mon, 30 Oct 2023 15:56:05 -0700
Subject: [PATCH 03/10] Only include set fields in jsonSerlialize output
This is more similar to the previous version and the output is much
more usable, particularly for things like Country.
---
src/Model/AnonymousIp.php | 33 ++++++---
src/Model/Asn.php | 18 +++--
src/Model/City.php | 24 +++++--
src/Model/ConnectionType.php | 13 ++--
src/Model/Country.php | 35 +++++++---
src/Model/Domain.php | 13 ++--
src/Model/Isp.php | 33 ++++++---
src/Record/AbstractPlaceRecord.php | 9 ++-
src/Record/Continent.php | 8 ++-
src/Record/Country.php | 8 ++-
src/Record/Location.php | 33 ++++++---
src/Record/MaxMind.php | 9 ++-
src/Record/Postal.php | 13 ++--
src/Record/RepresentedCountry.php | 4 +-
src/Record/Subdivision.php | 4 +-
src/Record/Traits.php | 89 +++++++++++++++++-------
tests/GeoIp2/Test/Model/CountryTest.php | 35 ----------
tests/GeoIp2/Test/Model/InsightsTest.php | 15 ++--
18 files changed, 257 insertions(+), 139 deletions(-)
diff --git a/src/Model/AnonymousIp.php b/src/Model/AnonymousIp.php
index 6cd9ef9d..c7445654 100644
--- a/src/Model/AnonymousIp.php
+++ b/src/Model/AnonymousIp.php
@@ -58,15 +58,28 @@ public function __construct(array $raw)
public function jsonSerialize(): ?array
{
- return [
- 'is_anonymous' => $this->isAnonymous,
- 'is_anonymous_vpn' => $this->isAnonymousVpn,
- 'is_hosting_provider' => $this->isHostingProvider,
- 'is_public_proxy' => $this->isPublicProxy,
- 'is_residential_proxy' => $this->isResidentialProxy,
- 'is_tor_exit_node' => $this->isTorExitNode,
- 'ip_address' => $this->ipAddress,
- 'network' => $this->network,
- ];
+ $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['ip_address'] = $this->ipAddress;
+ $js['network'] = $this->network;
+
+ return $js;
}
}
diff --git a/src/Model/Asn.php b/src/Model/Asn.php
index 1cb1aa11..0ccb7648 100644
--- a/src/Model/Asn.php
+++ b/src/Model/Asn.php
@@ -42,11 +42,17 @@ public function __construct(array $raw)
public function jsonSerialize(): ?array
{
- return [
- 'autonomous_system_number' => $this->autonomousSystemNumber,
- 'autonomous_system_organization' => $this->autonomousSystemOrganization,
- 'ip_address' => $this->ipAddress,
- 'network' => $this->network,
- ];
+ $js = [];
+
+ if ($this->autonomousSystemNumber !== null) {
+ $js['autonomous_system_number'] = $this->autonomousSystemNumber;
+ }
+ if ($this->autonomousSystemOrganization !== null) {
+ $js['autonomous_system_organization'] = $this->autonomousSystemOrganization;
+ }
+ $js['ip_address'] = $this->ipAddress;
+ $js['network'] = $this->network;
+
+ return $js;
}
}
diff --git a/src/Model/City.php b/src/Model/City.php
index 758ae1e5..2b7f5a81 100644
--- a/src/Model/City.php
+++ b/src/Model/City.php
@@ -4,6 +4,8 @@
namespace GeoIp2\Model;
+use GeoIp2\Record\Subdivision;
+
/**
* Model class for the data returned by City Plus web service and City
* database.
@@ -94,15 +96,29 @@ public function jsonSerialize(): ?array
{
$js = parent::jsonSerialize();
- $js['city'] = $this->city->jsonSerialize();
- $js['location'] = $this->location->jsonSerialize();
- $js['postal'] = $this->postal->jsonSerialize();
+ $city = $this->city->jsonSerialize();
+ if (!empty($city)) {
+ $js['city'] = $city;
+ }
+
+ $location = $this->location->jsonSerialize();
+ if (!empty($location)) {
+ $js['location'] = $location;
+ }
+
+ $postal =
+ $this->postal->jsonSerialize();
+ if (!empty($postal)) {
+ $js['postal'] = $postal;
+ }
$subdivisions = [];
foreach ($this->subdivisions as $sub) {
$subdivisions[] = $sub->jsonSerialize();
}
- $js['subdivisions'] = $subdivisions;
+ if (!empty($subdivisions)) {
+ $js['subdivisions'] = $subdivisions;
+ }
return $js;
}
diff --git a/src/Model/ConnectionType.php b/src/Model/ConnectionType.php
index 952835c1..4a236074 100644
--- a/src/Model/ConnectionType.php
+++ b/src/Model/ConnectionType.php
@@ -37,10 +37,13 @@ public function __construct(array $raw)
public function jsonSerialize(): ?array
{
- return [
- 'connection_type' => $this->connectionType,
- 'ip_address' => $this->ipAddress,
- 'network' => $this->network,
- ];
+ $js = [];
+ if ($this->connectionType !== null) {
+ $js['connection_type'] = $this->connectionType;
+ }
+ $js['ip_address'] = $this->ipAddress;
+ $js['network'] = $this->network;
+
+ return $js;
}
}
diff --git a/src/Model/Country.php b/src/Model/Country.php
index 95e459d7..364601ea 100644
--- a/src/Model/Country.php
+++ b/src/Model/Country.php
@@ -63,13 +63,32 @@ public function __construct(array $raw, array $locales = ['en'])
public function jsonSerialize(): ?array
{
- return [
- 'continent' => $this->continent->jsonSerialize(),
- 'country' => $this->country->jsonSerialize(),
- 'maxmind' => $this->maxmind->jsonSerialize(),
- 'registered_country' => $this->registeredCountry->jsonSerialize(),
- 'represented_country' => $this->representedCountry->jsonSerialize(),
- 'traits' => $this->traits->jsonSerialize(),
- ];
+ $js = [];
+ $continent = $this->continent->jsonSerialize();
+ if (!empty($continent)) {
+ $js['continent'] = $continent;
+ }
+ $country = $this->country->jsonSerialize();
+ if (!empty($country)) {
+ $js['country'] = $country;
+ }
+ $maxmind = $this->maxmind->jsonSerialize();
+ if (!empty($maxmind)) {
+ $js['maxmind'] = $maxmind;
+ }
+ $registeredCountry = $this->registeredCountry->jsonSerialize();
+ if (!empty($registeredCountry)) {
+ $js['registered_country'] = $registeredCountry;
+ }
+ $representedCountry = $this->representedCountry->jsonSerialize();
+ if (!empty($representedCountry)) {
+ $js['represented_country'] = $representedCountry;
+ }
+ $traits = $this->traits->jsonSerialize();
+ if (!empty($traits)) {
+ $js['traits'] = $traits;
+ }
+
+ return $js;
}
}
diff --git a/src/Model/Domain.php b/src/Model/Domain.php
index 4f04e7a1..c6e34374 100644
--- a/src/Model/Domain.php
+++ b/src/Model/Domain.php
@@ -37,10 +37,13 @@ public function __construct(array $raw)
public function jsonSerialize(): ?array
{
- return [
- 'domain' => $this->domain,
- 'ip_address' => $this->ipAddress,
- 'network' => $this->network,
- ];
+ $js = [];
+ if ($this->domain !== null) {
+ $js['domain'] = $this->domain;
+ }
+ $js['ip_address'] = $this->ipAddress;
+ $js['network'] = $this->network;
+
+ return $js;
}
}
diff --git a/src/Model/Isp.php b/src/Model/Isp.php
index afa480f0..574bdea0 100644
--- a/src/Model/Isp.php
+++ b/src/Model/Isp.php
@@ -61,15 +61,28 @@ public function __construct(array $raw)
public function jsonSerialize(): ?array
{
- return [
- 'autonomous_system_number' => $this->autonomousSystemNumber,
- 'autonomous_system_organization' => $this->autonomousSystemOrganization,
- 'isp' => $this->isp,
- 'mobile_country_code' => $this->mobileCountryCode,
- 'mobile_network_code' => $this->mobileNetworkCode,
- 'organization' => $this->organization,
- 'ip_address' => $this->ipAddress,
- 'network' => $this->network,
- ];
+ $js = [];
+ if ($this->autonomousSystemNumber !== null) {
+ $js['autonomous_system_number'] = $this->autonomousSystemNumber;
+ }
+ if ($this->autonomousSystemOrganization !== null) {
+ $js['autonomous_system_organization'] = $this->autonomousSystemOrganization;
+ }
+ if ($this->isp !== null) {
+ $js['isp'] = $this->isp;
+ }
+ if ($this->mobileCountryCode !== null) {
+ $js['mobile_country_code'] = $this->mobileCountryCode;
+ }
+ if ($this->mobileNetworkCode !== null) {
+ $js['mobile_network_code'] = $this->mobileNetworkCode;
+ }
+ if ($this->organization !== null) {
+ $js['organization'] = $this->organization;
+ }
+ $js['ip_address'] = $this->ipAddress;
+ $js['network'] = $this->network;
+
+ return $js;
}
}
diff --git a/src/Record/AbstractPlaceRecord.php b/src/Record/AbstractPlaceRecord.php
index e01ad88c..af8937ed 100644
--- a/src/Record/AbstractPlaceRecord.php
+++ b/src/Record/AbstractPlaceRecord.php
@@ -23,8 +23,13 @@ public function __construct(array $record, array $locales = ['en'])
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
- $js['confidence'] = $this->confidence;
- $js['geoname_id'] = $this->geonameId;
+ if ($this->confidence !== null) {
+ $js['confidence'] = $this->confidence;
+ }
+
+ if ($this->geonameId !== null) {
+ $js['geoname_id'] = $this->geonameId;
+ }
return $js;
}
diff --git a/src/Record/Continent.php b/src/Record/Continent.php
index 30fc37f9..7defaaf8 100644
--- a/src/Record/Continent.php
+++ b/src/Record/Continent.php
@@ -40,8 +40,12 @@ public function __construct(array $record, array $locales = ['en'])
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
- $js['code'] = $this->code;
- $js['geoname_id'] = $this->geonameId;
+ if ($this->code !== null) {
+ $js['code'] = $this->code;
+ }
+ if ($this->geonameId !== null) {
+ $js['geoname_id'] = $this->geonameId;
+ }
return $js;
}
diff --git a/src/Record/Country.php b/src/Record/Country.php
index d6e4cbb2..9d0a51f9 100644
--- a/src/Record/Country.php
+++ b/src/Record/Country.php
@@ -46,8 +46,12 @@ public function __construct(array $record, array $locales = ['en'])
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
- $js['is_in_european_union'] = $this->isInEuropeanUnion;
- $js['iso_code'] = $this->isoCode;
+ if ($this->isInEuropeanUnion !== false) {
+ $js['is_in_european_union'] = $this->isInEuropeanUnion;
+ }
+ if ($this->isoCode !== null) {
+ $js['iso_code'] = $this->isoCode;
+ }
return $js;
}
diff --git a/src/Record/Location.php b/src/Record/Location.php
index 369898f7..6cd42a3b 100644
--- a/src/Record/Location.php
+++ b/src/Record/Location.php
@@ -58,14 +58,29 @@ public function __construct(array $record)
public function jsonSerialize(): array
{
- return [
- 'average_income' => $this->averageIncome,
- 'accuracy_radius' => $this->accuracyRadius,
- 'latitude' => $this->latitude,
- 'longitude' => $this->longitude,
- 'metro_code' => $this->metroCode,
- 'population_density' => $this->populationDensity,
- 'time_zone' => $this->timeZone,
- ];
+ $js = [];
+ if ($this->averageIncome !== null) {
+ $js['average_income'] = $this->averageIncome;
+ }
+ if ($this->accuracyRadius !== null) {
+ $js['accuracy_radius'] = $this->accuracyRadius;
+ }
+ if ($this->latitude !== null) {
+ $js['latitude'] = $this->latitude;
+ }
+ if ($this->longitude !== null) {
+ $js['longitude'] = $this->longitude;
+ }
+ if ($this->metroCode !== null) {
+ $js['metro_code'] = $this->metroCode;
+ }
+ if ($this->populationDensity !== null) {
+ $js['population_density'] = $this->populationDensity;
+ }
+ if ($this->timeZone !== null) {
+ $js['time_zone'] = $this->timeZone;
+ }
+
+ return $js;
}
}
diff --git a/src/Record/MaxMind.php b/src/Record/MaxMind.php
index 2be550b8..51cd42e6 100644
--- a/src/Record/MaxMind.php
+++ b/src/Record/MaxMind.php
@@ -23,8 +23,11 @@ public function __construct(array $record)
public function jsonSerialize(): array
{
- return [
- 'queries_remaining' => $this->queriesRemaining,
- ];
+ $js = [];
+ if ($this->queriesRemaining !== null) {
+ $js['queries_remaining'] = $this->queriesRemaining;
+ }
+
+ return $js;
}
}
diff --git a/src/Record/Postal.php b/src/Record/Postal.php
index 05481b9d..d2e2e893 100644
--- a/src/Record/Postal.php
+++ b/src/Record/Postal.php
@@ -35,9 +35,14 @@ public function __construct(array $record)
public function jsonSerialize(): array
{
- return [
- 'code' => $this->code,
- 'confidence' => $this->confidence,
- ];
+ $js = [];
+ if ($this->code !== null) {
+ $js['code'] = $this->code;
+ }
+ if ($this->confidence !== null) {
+ $js['confidence'] = $this->confidence;
+ }
+
+ return $js;
}
}
diff --git a/src/Record/RepresentedCountry.php b/src/Record/RepresentedCountry.php
index 6e857326..530f02c5 100644
--- a/src/Record/RepresentedCountry.php
+++ b/src/Record/RepresentedCountry.php
@@ -32,7 +32,9 @@ public function __construct(array $record, array $locales = ['en'])
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
- $js['type'] = $this->type;
+ if ($this->type !== null) {
+ $js['type'] = $this->type;
+ }
return $js;
}
diff --git a/src/Record/Subdivision.php b/src/Record/Subdivision.php
index 7ae7f3c7..5489f981 100644
--- a/src/Record/Subdivision.php
+++ b/src/Record/Subdivision.php
@@ -45,7 +45,9 @@ public function __construct(array $record, array $locales = ['en'])
public function jsonSerialize(): array
{
$js = parent::jsonSerialize();
- $js['iso_code'] = $this->isoCode;
+ if ($this->isoCode !== null) {
+ $js['iso_code'] = $this->isoCode;
+ }
return $js;
}
diff --git a/src/Record/Traits.php b/src/Record/Traits.php
index 0e72ccee..1a30dcca 100644
--- a/src/Record/Traits.php
+++ b/src/Record/Traits.php
@@ -174,29 +174,70 @@ public function __construct(array $record)
public function jsonSerialize(): array
{
- return [
- 'autonomous_system_number' => $this->autonomousSystemNumber,
- 'autonomous_system_organization' => $this->autonomousSystemOrganization,
- 'connection_type' => $this->connectionType,
- 'domain' => $this->domain,
- 'ip_address' => $this->ipAddress,
- 'is_anonymous' => $this->isAnonymous,
- 'is_anonymous_proxy' => $this->isAnonymousProxy,
- 'is_anonymous_vpn' => $this->isAnonymousVpn,
- 'is_hosting_provider' => $this->isHostingProvider,
- 'is_legitimate_proxy' => $this->isLegitimateProxy,
- 'is_public_proxy' => $this->isPublicProxy,
- 'is_residential_proxy' => $this->isResidentialProxy,
- 'is_satellite_provider' => $this->isSatelliteProvider,
- 'is_tor_exit_node' => $this->isTorExitNode,
- 'isp' => $this->isp,
- 'mobile_country_code' => $this->mobileCountryCode,
- 'mobile_network_code' => $this->mobileNetworkCode,
- 'network' => $this->network,
- 'organization' => $this->organization,
- 'static_ip_score' => $this->staticIpScore,
- 'user_count' => $this->userCount,
- 'user_type' => $this->userType,
- ];
+ $js = [];
+ if ($this->autonomousSystemNumber !== null) {
+ $js['autonomous_system_number'] = $this->autonomousSystemNumber;
+ }
+ if ($this->autonomousSystemOrganization !== null) {
+ $js['autonomous_system_organization'] = $this->autonomousSystemOrganization;
+ }
+ if ($this->connectionType !== null) {
+ $js['connection_type'] = $this->connectionType;
+ }
+ if ($this->domain !== null) {
+ $js['domain'] = $this->domain;
+ }
+ $js['ip_address'] = $this->ipAddress;
+ if ($this->isAnonymous !== false) {
+ $js['is_anonymous'] = $this->isAnonymous;
+ }
+ if ($this->isAnonymousProxy !== false) {
+ $js['is_anonymous_proxy'] = $this->isAnonymousProxy;
+ }
+ if ($this->isAnonymousVpn !== false) {
+ $js['is_anonymous_vpn'] = $this->isAnonymousVpn;
+ }
+ if ($this->isHostingProvider !== false) {
+ $js['is_hosting_provider'] = $this->isHostingProvider;
+ }
+ if ($this->isLegitimateProxy !== false) {
+ $js['is_legitimate_proxy'] = $this->isLegitimateProxy;
+ }
+ if ($this->isPublicProxy !== false) {
+ $js['is_public_proxy'] = $this->isPublicProxy;
+ }
+ if ($this->isResidentialProxy !== false) {
+ $js['is_residential_proxy'] = $this->isResidentialProxy;
+ }
+ if ($this->isSatelliteProvider !== false) {
+ $js['is_satellite_provider'] = $this->isSatelliteProvider;
+ }
+ if ($this->isTorExitNode !== false) {
+ $js['is_tor_exit_node'] = $this->isTorExitNode;
+ }
+ if ($this->isp !== null) {
+ $js['isp'] = $this->isp;
+ }
+ if ($this->mobileCountryCode !== null) {
+ $js['mobile_country_code'] = $this->mobileCountryCode;
+ }
+ if ($this->mobileNetworkCode !== null) {
+ $js['mobile_network_code'] = $this->mobileNetworkCode;
+ }
+ $js['network'] = $this->network;
+ if ($this->organization !== null) {
+ $js['organization'] = $this->organization;
+ }
+ if ($this->staticIpScore !== null) {
+ $js['static_ip_score'] = $this->staticIpScore;
+ }
+ if ($this->userCount !== null) {
+ $js['user_count'] = $this->userCount;
+ }
+ if ($this->userType !== null) {
+ $js['user_type'] = $this->userType;
+ }
+
+ return $js;
}
}
diff --git a/tests/GeoIp2/Test/Model/CountryTest.php b/tests/GeoIp2/Test/Model/CountryTest.php
index 41e22de2..fba0dbc1 100644
--- a/tests/GeoIp2/Test/Model/CountryTest.php
+++ b/tests/GeoIp2/Test/Model/CountryTest.php
@@ -186,54 +186,19 @@ public function testJsonSerialize(): void
'country' => [
'name' => 'United States of America',
'names' => ['en' => 'United States of America'],
- 'confidence' => null,
'geoname_id' => 1,
- 'is_in_european_union' => false,
'iso_code' => 'US',
],
- 'maxmind' => [
- 'queries_remaining' => null,
- ],
'registered_country' => [
'name' => 'Germany',
'names' => ['en' => 'Germany'],
- 'confidence' => null,
'geoname_id' => 2,
'is_in_european_union' => true,
'iso_code' => 'DE',
],
- 'represented_country' => [
- 'name' => null,
- 'names' => [],
- 'confidence' => null,
- 'geoname_id' => null,
- 'is_in_european_union' => false,
- 'iso_code' => null,
- 'type' => null,
- ],
'traits' => [
- 'autonomous_system_number' => null,
- 'autonomous_system_organization' => null,
- 'connection_type' => null,
- 'domain' => null,
'ip_address' => '1.2.3.4',
- 'is_anonymous' => false,
- 'is_anonymous_proxy' => false,
- 'is_anonymous_vpn' => false,
- 'is_hosting_provider' => false,
- 'is_legitimate_proxy' => false,
- 'is_public_proxy' => false,
- 'is_residential_proxy' => false,
- 'is_satellite_provider' => false,
- 'is_tor_exit_node' => false,
- 'isp' => null,
- 'mobile_country_code' => null,
- 'mobile_network_code' => null,
'network' => '1.2.3.0/24',
- 'organization' => null,
- 'static_ip_score' => null,
- 'user_count' => null,
- 'user_type' => null,
],
];
$this->assertSame(
diff --git a/tests/GeoIp2/Test/Model/InsightsTest.php b/tests/GeoIp2/Test/Model/InsightsTest.php
index c4252779..f7f14017 100644
--- a/tests/GeoIp2/Test/Model/InsightsTest.php
+++ b/tests/GeoIp2/Test/Model/InsightsTest.php
@@ -50,13 +50,11 @@ public function testFull(): void
'confidence' => 33,
],
'registered_country' => [
- 'confidence' => null,
'geoname_id' => 2,
'iso_code' => 'CA',
'names' => ['en' => 'Canada'],
],
'represented_country' => [
- 'confidence' => null,
'geoname_id' => 3,
'iso_code' => 'GB',
'names' => ['en' => 'United Kingdom'],
@@ -247,7 +245,6 @@ public function testFull(): void
'names' => ['en' => 'United States of America'],
'confidence' => 99,
'geoname_id' => 1,
- 'is_in_european_union' => false,
'iso_code' => 'US',
],
'maxmind' => [
@@ -256,17 +253,13 @@ public function testFull(): void
'registered_country' => [
'name' => 'Canada',
'names' => ['en' => 'Canada'],
- 'confidence' => null,
'geoname_id' => 2,
- 'is_in_european_union' => false,
'iso_code' => 'CA',
],
'represented_country' => [
'name' => 'United Kingdom',
'names' => ['en' => 'United Kingdom'],
- 'confidence' => null,
'geoname_id' => 3,
- 'is_in_european_union' => false,
'iso_code' => 'GB',
'type' => 'military',
],
@@ -330,7 +323,7 @@ public function testFull(): void
public function testEmptyObjects(): void
{
- $raw = ['traits' => ['ip_address' => '5.6.7.8']];
+ $raw = ['traits' => ['ip_address' => '5.6.7.8', 'network' => '5.6.7.0/24']];
$model = new Insights($raw, ['en']);
@@ -393,6 +386,12 @@ public function testEmptyObjects(): void
$model->traits,
'$model->traits'
);
+
+ $this->assertSame(
+ $raw,
+ $model->jsonSerialize(),
+ 'jsonSerialize',
+ );
}
public function testUnknown(): void
From 5aaf99258ccd71f1fe283d99a50d2a96a564e4ff Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 10:02:14 -0700
Subject: [PATCH 04/10] Upgrade to phpunit 10
---
.github/workflows/test.yml | 2 +-
composer.json | 2 +-
phpunit.xml.dist | 30 +++++++++--------------
tests/GeoIp2/Test/Database/ReaderTest.php | 2 +-
4 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6c434809..14ea6937 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -33,4 +33,4 @@ jobs:
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Test with phpunit
- run: vendor/bin/phpunit --coverage-text
+ run: vendor/bin/phpunit
diff --git a/composer.json b/composer.json
index a45a613d..74616276 100644
--- a/composer.json
+++ b/composer.json
@@ -20,7 +20,7 @@
},
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
- "phpunit/phpunit": "^9.0",
+ "phpunit/phpunit": "^10.0",
"squizlabs/php_codesniffer": "3.*",
"phpstan/phpstan": "*"
},
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 5125feff..b87ac45a 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,20 +1,14 @@
-
-
-
-
- ./tests/GeoIp2/Test/
-
-
-
-
-
- ./src/GeoIp2/
-
-
-
-
-
-
-
+
+
+
+ ./tests/GeoIp2/Test/
+
+
+
+
diff --git a/tests/GeoIp2/Test/Database/ReaderTest.php b/tests/GeoIp2/Test/Database/ReaderTest.php
index fbbb3468..a7091137 100644
--- a/tests/GeoIp2/Test/Database/ReaderTest.php
+++ b/tests/GeoIp2/Test/Database/ReaderTest.php
@@ -14,7 +14,7 @@
*/
class ReaderTest extends TestCase
{
- public function databaseTypes(): array
+ public static function databaseTypes(): array
{
return [['City', 'city'], ['Country', 'country']];
}
From 826b90ec5e4d81e1b75c7c525a2a2849d6bf8c8c Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 10:03:46 -0700
Subject: [PATCH 05/10] Use vendor/autoload.php to bootstrap directly
---
phpunit.xml.dist | 2 +-
tests/bootstrap.php | 9 ---------
2 files changed, 1 insertion(+), 10 deletions(-)
delete mode 100644 tests/bootstrap.php
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index b87ac45a..583a1a98 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,5 +1,5 @@
-
+./tests/GeoIp2/Test/
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
deleted file mode 100644
index 02c0592f..00000000
--- a/tests/bootstrap.php
+++ /dev/null
@@ -1,9 +0,0 @@
-add('GeoIp2\Test', __DIR__);
From 9dbb207f8ce5bd430038d76a15a6dd134bf176c6 Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 13:39:30 -0700
Subject: [PATCH 06/10] Do not include name in JSON output
This makes is more similar to the web-service response.
---
src/Record/AbstractNamedRecord.php | 3 ---
tests/GeoIp2/Test/Model/CountryTest.php | 3 ---
tests/GeoIp2/Test/Model/InsightsTest.php | 6 ------
3 files changed, 12 deletions(-)
diff --git a/src/Record/AbstractNamedRecord.php b/src/Record/AbstractNamedRecord.php
index 79a49277..7e8758f9 100644
--- a/src/Record/AbstractNamedRecord.php
+++ b/src/Record/AbstractNamedRecord.php
@@ -29,9 +29,6 @@ public function __construct(array $record, array $locales = ['en'])
public function jsonSerialize(): array
{
$js = [];
- if ($this->name !== null) {
- $js['name'] = $this->name;
- }
if (!empty($this->names)) {
$js['names'] = $this->names;
}
diff --git a/tests/GeoIp2/Test/Model/CountryTest.php b/tests/GeoIp2/Test/Model/CountryTest.php
index fba0dbc1..c8cf92fd 100644
--- a/tests/GeoIp2/Test/Model/CountryTest.php
+++ b/tests/GeoIp2/Test/Model/CountryTest.php
@@ -178,19 +178,16 @@ public function testJsonSerialize(): void
$js =
[
'continent' => [
- 'name' => 'North America',
'names' => ['en' => 'North America'],
'code' => 'NA',
'geoname_id' => 42,
],
'country' => [
- 'name' => 'United States of America',
'names' => ['en' => 'United States of America'],
'geoname_id' => 1,
'iso_code' => 'US',
],
'registered_country' => [
- 'name' => 'Germany',
'names' => ['en' => 'Germany'],
'geoname_id' => 2,
'is_in_european_union' => true,
diff --git a/tests/GeoIp2/Test/Model/InsightsTest.php b/tests/GeoIp2/Test/Model/InsightsTest.php
index f7f14017..39815073 100644
--- a/tests/GeoIp2/Test/Model/InsightsTest.php
+++ b/tests/GeoIp2/Test/Model/InsightsTest.php
@@ -235,13 +235,11 @@ public function testFull(): void
$this->assertSame(
[
'continent' => [
- 'name' => 'North America',
'names' => ['en' => 'North America'],
'code' => 'NA',
'geoname_id' => 42,
],
'country' => [
- 'name' => 'United States of America',
'names' => ['en' => 'United States of America'],
'confidence' => 99,
'geoname_id' => 1,
@@ -251,13 +249,11 @@ public function testFull(): void
'queries_remaining' => 22,
],
'registered_country' => [
- 'name' => 'Canada',
'names' => ['en' => 'Canada'],
'geoname_id' => 2,
'iso_code' => 'CA',
],
'represented_country' => [
- 'name' => 'United Kingdom',
'names' => ['en' => 'United Kingdom'],
'geoname_id' => 3,
'iso_code' => 'GB',
@@ -288,7 +284,6 @@ public function testFull(): void
'user_type' => 'college',
],
'city' => [
- 'name' => 'Minneapolis',
'names' => ['en' => 'Minneapolis'],
'confidence' => 76,
'geoname_id' => 9876,
@@ -308,7 +303,6 @@ public function testFull(): void
],
'subdivisions' => [
[
- 'name' => 'Minnesota',
'names' => ['en' => 'Minnesota'],
'confidence' => 88,
'geoname_id' => 574635,
From dc20c431c8b1f605e7a5668ff9c5b227bcd14ae6 Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 13:42:32 -0700
Subject: [PATCH 07/10] Make ipAddress and network nullable
This is needed for minFraud.
---
src/Record/Traits.php | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/Record/Traits.php b/src/Record/Traits.php
index 1a30dcca..b6b4052a 100644
--- a/src/Record/Traits.php
+++ b/src/Record/Traits.php
@@ -31,7 +31,7 @@
* not "foo.example.com". This attribute is only available from the
* City Plus and Insights web services and the GeoIP2 Enterprise
* database.
- * @property-read string $ipAddress The IP address that the data in the model
+ * @property-read string|null $ipAddress The IP address that the data in the model
* is for. If you performed a "me" lookup against the web service, this
* will be the externally routable IP address for the system the code is
* running on. If the system is behind a NAT, this may differ from the IP
@@ -70,7 +70,7 @@
* @property-read string|null $isp The name of the ISP 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 $network The network in CIDR notation associated with
+ * @property-read string|null $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
@@ -122,7 +122,7 @@ class Traits implements \JsonSerializable
public readonly ?string $autonomousSystemOrganization;
public readonly ?string $connectionType;
public readonly ?string $domain;
- public readonly string $ipAddress;
+ public readonly ?string $ipAddress;
public readonly bool $isAnonymous;
public readonly bool $isAnonymousProxy;
public readonly bool $isAnonymousVpn;
@@ -135,7 +135,7 @@ class Traits implements \JsonSerializable
public readonly bool $isTorExitNode;
public readonly ?string $mobileCountryCode;
public readonly ?string $mobileNetworkCode;
- public readonly string $network;
+ public readonly ?string $network;
public readonly ?string $organization;
public readonly ?float $staticIpScore;
public readonly ?int $userCount;
@@ -168,7 +168,7 @@ public function __construct(array $record)
if (isset($record['network'])) {
$this->network = $record['network'];
} else {
- $this->network = Util::cidr($this->ipAddress, $record['prefix_len'] ?? 0);
+ $this->network = isset($record['prefix_len']) ? Util::cidr($this->ipAddress, $record['prefix_len']) : null;
}
}
@@ -187,7 +187,9 @@ public function jsonSerialize(): array
if ($this->domain !== null) {
$js['domain'] = $this->domain;
}
- $js['ip_address'] = $this->ipAddress;
+ if ($this->ipAddress !== null) {
+ $js['ip_address'] = $this->ipAddress;
+ }
if ($this->isAnonymous !== false) {
$js['is_anonymous'] = $this->isAnonymous;
}
@@ -224,7 +226,9 @@ public function jsonSerialize(): array
if ($this->mobileNetworkCode !== null) {
$js['mobile_network_code'] = $this->mobileNetworkCode;
}
- $js['network'] = $this->network;
+ if ($this->network !== null) {
+ $js['network'] = $this->network;
+ }
if ($this->organization !== null) {
$js['organization'] = $this->organization;
}
From 442d0a20af358e1adf202a655a5a2bc4f99750e1 Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 14:56:31 -0700
Subject: [PATCH 08/10] Move docs to the properties
Previously this was not possible as we were using magic methods.
---
src/Model/AnonymousIp.php | 62 ++++---
src/Model/Asn.php | 32 ++--
src/Model/City.php | 44 ++---
src/Model/ConnectionType.php | 25 ++-
src/Model/Country.php | 51 ++++--
src/Model/Domain.php | 25 ++-
src/Model/Isp.php | 64 ++++---
src/Record/AbstractNamedRecord.php | 11 ++
src/Record/AbstractPlaceRecord.php | 10 ++
src/Record/City.php | 12 --
src/Record/Continent.php | 22 ++-
src/Record/Country.php | 29 ++-
src/Record/Location.php | 69 ++++---
src/Record/MaxMind.php | 7 +-
src/Record/Postal.php | 22 ++-
src/Record/RepresentedCountry.php | 9 +-
src/Record/Subdivision.php | 24 +--
src/Record/Traits.php | 280 ++++++++++++++++++-----------
18 files changed, 476 insertions(+), 322 deletions(-)
diff --git a/src/Model/AnonymousIp.php b/src/Model/AnonymousIp.php
index c7445654..7e3b9b6e 100644
--- a/src/Model/AnonymousIp.php
+++ b/src/Model/AnonymousIp.php
@@ -8,36 +8,58 @@
/**
* This class provides the GeoIP2 Anonymous IP model.
- *
- * @property-read bool $isAnonymous This is true if the IP address belongs to
- * any sort of anonymous network.
- * @property-read bool $isAnonymousVpn This is true if the IP address is
- * 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.
- * @property-read bool $isHostingProvider This is true if the IP address belongs
- * to a hosting or VPN provider (see description of isAnonymousVpn property).
- * @property-read bool $isPublicProxy This is true if the IP address belongs to
- * a public proxy.
- * @property-read bool $isResidentialProxy This is true if the IP address is
- * on a suspected anonymizing network and belongs to a residential ISP.
- * @property-read bool $isTorExitNode This is true if the IP address is a Tor
- * exit node.
- * @property-read string $ipAddress The IP address that the data in the model is
- * for.
- * @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.
*/
class AnonymousIp implements \JsonSerializable
{
+ /**
+ * @var bool this is true if the IP address belongs to
+ * any sort of anonymous network
+ */
public readonly bool $isAnonymous;
+
+ /**
+ * @var bool This is true if the IP address is
+ * 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.
+ */
public readonly bool $isAnonymousVpn;
+
+ /**
+ * @var bool this is true if the IP address belongs
+ * to a hosting or VPN provider (see description of isAnonymousVpn property)
+ */
public readonly bool $isHostingProvider;
+
+ /**
+ * @var bool this is true if the IP address belongs to
+ * a public proxy
+ */
public readonly bool $isPublicProxy;
+
+ /**
+ * @var bool this is true if the IP address is
+ * on a suspected anonymizing network and belongs to a residential ISP
+ */
public readonly bool $isResidentialProxy;
+
+ /**
+ * @var bool this is true if the IP address is a Tor
+ * exit node
+ */
public readonly bool $isTorExitNode;
+
+ /**
+ * @var string the IP address that the data in the model is
+ * for
+ */
public readonly string $ipAddress;
+
+ /**
+ * @var string 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.
+ */
public readonly string $network;
/**
diff --git a/src/Model/Asn.php b/src/Model/Asn.php
index 0ccb7648..55b85c5e 100644
--- a/src/Model/Asn.php
+++ b/src/Model/Asn.php
@@ -8,23 +8,33 @@
/**
* This class provides the GeoLite2 ASN model.
- *
- * @property-read int|null $autonomousSystemNumber The autonomous system number
- * associated with the IP address.
- * @property-read string|null $autonomousSystemOrganization The organization
- * associated with the registered autonomous system number for the IP
- * address.
- * @property-read string $ipAddress The IP address that the data in the model is
- * for.
- * @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.
*/
class Asn implements \JsonSerializable
{
+ /**
+ * @var int|null the autonomous system number
+ * associated with the IP address
+ */
public readonly ?int $autonomousSystemNumber;
+
+ /**
+ * @var string|null the organization
+ * associated with the registered autonomous system number for the IP
+ * address
+ */
public readonly ?string $autonomousSystemOrganization;
+
+ /**
+ * @var string the IP address that the data in the model is
+ * for
+ */
public readonly string $ipAddress;
+
+ /**
+ * @var string 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.
+ */
public readonly string $network;
/**
diff --git a/src/Model/City.php b/src/Model/City.php
index 2b7f5a81..f89ccfe4 100644
--- a/src/Model/City.php
+++ b/src/Model/City.php
@@ -4,59 +4,49 @@
namespace GeoIp2\Model;
-use GeoIp2\Record\Subdivision;
-
/**
* Model class for the data returned by City Plus web service and City
* database.
*
* 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.
- * @property-read \GeoIp2\Record\Location $location Location data for the
- * requested IP address.
- * @property-read \GeoIp2\Record\Postal $postal Postal data for the
- * requested IP address.
- * @property-read array $subdivisions An array \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.
- * @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision 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.
*/
class City extends Country
{
/**
- * @ignore
+ * @var \GeoIp2\Record\City city data for the requested IP
+ * address
*/
public readonly \GeoIp2\Record\City $city;
/**
- * @ignore
+ * @var \GeoIp2\Record\Location location data for the
+ * requested IP address
*/
public readonly \GeoIp2\Record\Location $location;
/**
- * @ignore
+ * @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.
*/
public readonly \GeoIp2\Record\Subdivision $mostSpecificSubdivision;
/**
- * @ignore
+ * @var \GeoIp2\Record\Postal postal data for the
+ * requested IP address
*/
public readonly \GeoIp2\Record\Postal $postal;
/**
- * @ignore
- *
- * @var array<\GeoIp2\Record\Subdivision>
+ * @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.
*/
public readonly array $subdivisions;
diff --git a/src/Model/ConnectionType.php b/src/Model/ConnectionType.php
index 4a236074..6facb5e8 100644
--- a/src/Model/ConnectionType.php
+++ b/src/Model/ConnectionType.php
@@ -8,20 +8,27 @@
/**
* This class provides the GeoIP2 Connection-Type model.
- *
- * @property-read string|null $connectionType The connection type may take the
- * following values: "Dialup", "Cable/DSL", "Corporate", "Cellular", and
- * "Satellite". Additional values may be added in the future.
- * @property-read string $ipAddress The IP address that the data in the model is
- * for.
- * @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.
*/
class ConnectionType implements \JsonSerializable
{
+ /**
+ * @var string|null The connection type may take the
+ * following values: "Dialup", "Cable/DSL", "Corporate", "Cellular", and
+ * "Satellite". Additional values may be added in the future.
+ */
public readonly ?string $connectionType;
+
+ /**
+ * @var string the IP address that the data in the model is
+ * for
+ */
public readonly string $ipAddress;
+
+ /**
+ * @var string 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.
+ */
public readonly string $network;
/**
diff --git a/src/Model/Country.php b/src/Model/Country.php
index 364601ea..0fae2db7 100644
--- a/src/Model/Country.php
+++ b/src/Model/Country.php
@@ -8,32 +8,47 @@
* Model class for the data returned by GeoIP2 Country web service and database.
*
* 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.
- * @property-read \GeoIp2\Record\Country $country Country data for the requested
- * IP address. This object represents the country where MaxMind believes the
- * end user is located.
- * @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
- * account.
- * @property-read \GeoIp2\Record\Country $registeredCountry 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.
- * @property-read \GeoIp2\Record\RepresentedCountry $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.
- * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
- * requested IP address.
*/
class Country implements \JsonSerializable
{
+ /**
+ * @var \GeoIp2\Record\Continent continent data for the
+ * requested IP address
+ */
public readonly \GeoIp2\Record\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.
+ */
public readonly \GeoIp2\Record\Country $country;
+
+ /**
+ * @var \GeoIp2\Record\MaxMind data related to your MaxMind
+ * account
+ */
public readonly \GeoIp2\Record\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.
+ */
public readonly \GeoIp2\Record\Country $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.
+ */
public readonly \GeoIp2\Record\RepresentedCountry $representedCountry;
+
+ /**
+ * @var \GeoIp2\Record\Traits data for the traits of the
+ * requested IP address
+ */
public readonly \GeoIp2\Record\Traits $traits;
/**
diff --git a/src/Model/Domain.php b/src/Model/Domain.php
index c6e34374..1ce83fdb 100644
--- a/src/Model/Domain.php
+++ b/src/Model/Domain.php
@@ -8,20 +8,27 @@
/**
* This class provides the GeoIP2 Domain model.
- *
- * @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".
- * @property-read string $ipAddress The IP address that the data in the model is
- * for.
- * @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.
*/
class Domain implements \JsonSerializable
{
+ /**
+ * @var string|null The second level domain associated with the
+ * IP address. This will be something like "example.com" or
+ * "example.co.uk", not "foo.example.com".
+ */
public readonly ?string $domain;
+
+ /**
+ * @var string the IP address that the data in the model is
+ * for
+ */
public readonly string $ipAddress;
+
+ /**
+ * @var string 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.
+ */
public readonly string $network;
/**
diff --git a/src/Model/Isp.php b/src/Model/Isp.php
index 574bdea0..f329063e 100644
--- a/src/Model/Isp.php
+++ b/src/Model/Isp.php
@@ -8,37 +8,59 @@
/**
* This class provides the GeoIP2 ISP model.
- *
- * @property-read int|null $autonomousSystemNumber The autonomous system number
- * associated with the IP address.
- * @property-read string|null $autonomousSystemOrganization The organization
- * associated with the registered autonomous system number for the IP
- * 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
- * for.
- * @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.
*/
class Isp implements \JsonSerializable
{
+ /**
+ * @var int|null the autonomous system number
+ * associated with the IP address
+ */
public readonly ?int $autonomousSystemNumber;
+
+ /**
+ * @var string|null the organization
+ * associated with the registered autonomous system number for the IP
+ * address
+ */
public readonly ?string $autonomousSystemOrganization;
+
+ /**
+ * @var string|null the name of the ISP associated with the IP
+ * address
+ */
public readonly ?string $isp;
+
+ /**
+ * @var string|null The [mobile country code
+ * (MCC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with
+ * the IP address and ISP.
+ */
public readonly ?string $mobileCountryCode;
+
+ /**
+ * @var string|null The [mobile network code
+ * (MNC)](https://en.wikipedia.org/wiki/Mobile_country_code) associated with
+ * the IP address and ISP.
+ */
public readonly ?string $mobileNetworkCode;
+
+ /**
+ * @var string|null the name of the organization associated
+ * with the IP address
+ */
public readonly ?string $organization;
+
+ /**
+ * @var string the IP address that the data in the model is
+ * for
+ */
public readonly string $ipAddress;
+
+ /**
+ * @var string 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.
+ */
public readonly string $network;
/**
diff --git a/src/Record/AbstractNamedRecord.php b/src/Record/AbstractNamedRecord.php
index 7e8758f9..414841d5 100644
--- a/src/Record/AbstractNamedRecord.php
+++ b/src/Record/AbstractNamedRecord.php
@@ -6,7 +6,18 @@
abstract class AbstractNamedRecord implements \JsonSerializable
{
+ /**
+ * @var string|null The name based on the locales list
+ * passed to the constructor. This attribute is returned by all location
+ * services and databases.
+ */
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.
+ */
public readonly array $names;
/**
diff --git a/src/Record/AbstractPlaceRecord.php b/src/Record/AbstractPlaceRecord.php
index af8937ed..364d7bb8 100644
--- a/src/Record/AbstractPlaceRecord.php
+++ b/src/Record/AbstractPlaceRecord.php
@@ -6,7 +6,17 @@
abstract class AbstractPlaceRecord extends AbstractNamedRecord
{
+ /**
+ * @var int|null A value from 0-100 indicating MaxMind's
+ * confidence that the location level is correct. This attribute is only available
+ * from the Insights service and the GeoIP2 Enterprise database.
+ */
public readonly ?int $confidence;
+
+ /**
+ * @var int|null The GeoName ID for the location level. This attribute
+ * is returned by all location services and databases.
+ */
public readonly ?int $geonameId;
/**
diff --git a/src/Record/City.php b/src/Record/City.php
index cf27fc84..9ebb9a28 100644
--- a/src/Record/City.php
+++ b/src/Record/City.php
@@ -9,18 +9,6 @@
*
* This record is returned by all location services and databases besides
* Country.
- *
- * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
- * confidence that the city is correct. This attribute is only available
- * from the Insights service and the GeoIP2 Enterprise database.
- * @property-read int|null $geonameId The GeoName ID for the city. This attribute
- * is returned by all location services and databases.
- * @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 An array map where the keys are locale codes
- * and the values are names. This attribute is returned by all location
- * services and databases.
*/
// phpcs:disable
class City extends AbstractPlaceRecord {}
diff --git a/src/Record/Continent.php b/src/Record/Continent.php
index 7defaaf8..873014ae 100644
--- a/src/Record/Continent.php
+++ b/src/Record/Continent.php
@@ -8,22 +8,20 @@
* Contains data for the continent record associated with an IP address.
*
* This record is returned by all location services and databases.
- *
- * @property-read string|null $code A two character continent code like "NA" (North
- * America) or "OC" (Oceania). This attribute is returned by all location
- * services and databases.
- * @property-read int|null $geonameId The GeoName ID for the continent. This
- * attribute is returned by all location services and databases.
- * @property-read string|null $name Returns the name of the continent based on the
- * locales list passed to the constructor. This attribute is returned by all location
- * services and databases.
- * @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.
*/
class Continent extends AbstractNamedRecord
{
+ /**
+ * @var string|null A two character continent code like "NA" (North
+ * America) or "OC" (Oceania). This attribute is returned by all location
+ * services and databases.
+ */
public readonly ?string $code;
+
+ /**
+ * @var int|null The GeoName ID for the continent. This
+ * attribute is returned by all location services and databases.
+ */
public readonly ?int $geonameId;
/**
diff --git a/src/Record/Country.php b/src/Record/Country.php
index 9d0a51f9..438ebd89 100644
--- a/src/Record/Country.php
+++ b/src/Record/Country.php
@@ -8,28 +8,21 @@
* Contains data for the country record associated with an IP address.
*
* This record is returned by all location services and databases.
- *
- * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
- * confidence that the country is correct. This attribute is only available
- * from the Insights service and the GeoIP2 Enterprise database.
- * @property-read int|null $geonameId The GeoName ID for the country. This
- * attribute is returned by all location services and databases.
- * @property-read bool $isInEuropeanUnion This is true if the country is a
- * member state of the European Union. This attribute is returned by all
- * location services and databases.
- * @property-read string|null $isoCode The two-character ISO 3166-1 alpha code
- * for the country. See https://en.wikipedia.org/wiki/ISO_3166-1. This
- * attribute is returned by all location services and databases.
- * @property-read string|null $name The name of the country based on the locales
- * list passed to the constructor. This attribute is returned by all location
- * services and databases.
- * @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.
*/
class Country extends AbstractPlaceRecord
{
+ /**
+ * @var bool This is true if the country is a
+ * member state of the European Union. This attribute is returned by all
+ * location services and databases.
+ */
public readonly bool $isInEuropeanUnion;
+
+ /**
+ * @var string|null The two-character ISO 3166-1 alpha code
+ * for the country. See https://en.wikipedia.org/wiki/ISO_3166-1. This
+ * attribute is returned by all location services and databases.
+ */
public readonly ?string $isoCode;
/**
diff --git a/src/Record/Location.php b/src/Record/Location.php
index 6cd42a3b..ca13b52c 100644
--- a/src/Record/Location.php
+++ b/src/Record/Location.php
@@ -9,40 +9,59 @@
*
* This record is returned by all location services and databases besides
* Country.
- *
- * @property-read int|null $averageIncome The average income in US dollars
- * associated with the requested IP address. This attribute is only available
- * from the Insights service.
- * @property-read int|null $accuracyRadius The approximate accuracy radius in
- * kilometers around the latitude and longitude for the IP address. This is
- * the radius where we have a 67% confidence that the device using the IP
- * address resides within the circle centered at the latitude and longitude
- * with the provided radius.
- * @property-read float|null $latitude The approximate latitude of the location
- * associated with the IP address. This value is not precise and should not be
- * used to identify a particular address or household.
- * @property-read float|null $longitude The approximate longitude of the location
- * associated with the IP address. This value is not precise and should not be
- * used to identify a particular address or household.
- * @property-read int|null $populationDensity The estimated population per square
- * kilometer associated with the IP address. This attribute is only available
- * from the Insights service.
- * @property-read int|null $metroCode 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.
- * @property-read string|null $timeZone The time zone associated with location, as
- * specified by the IANA Time Zone Database, e.g., "America/New_York". See
- * https://www.iana.org/time-zones.
*/
class Location implements \JsonSerializable
{
+ /**
+ * @var int|null The average income in US dollars
+ * associated with the requested IP address. This attribute is only available
+ * from the Insights service.
+ */
public readonly ?int $averageIncome;
+
+ /**
+ * @var int|null The approximate accuracy radius in
+ * kilometers around the latitude and longitude for the IP address. This is
+ * the radius where we have a 67% confidence that the device using the IP
+ * address resides within the circle centered at the latitude and longitude
+ * with the provided radius.
+ */
public readonly ?int $accuracyRadius;
+
+ /**
+ * @var float|null The approximate latitude of the location
+ * associated with the IP address. This value is not precise and should not be
+ * used to identify a particular address or household.
+ */
public readonly ?float $latitude;
+
+ /**
+ * @var float|null The approximate longitude of the location
+ * associated with the IP address. This value is not precise and should not be
+ * used to identify a particular address or household.
+ */
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.
+ */
public readonly ?int $metroCode;
+
+ /**
+ * @var int|null The estimated population per square
+ * kilometer associated with the IP address. This attribute is only available
+ * from the Insights service.
+ */
public readonly ?int $populationDensity;
+
+ /**
+ * @var string|null The time zone associated with location, as
+ * specified by the IANA Time Zone Database, e.g., "America/New_York". See
+ * https://www.iana.org/time-zones.
+ */
public readonly ?string $timeZone;
public function __construct(array $record)
diff --git a/src/Record/MaxMind.php b/src/Record/MaxMind.php
index 51cd42e6..e80334d5 100644
--- a/src/Record/MaxMind.php
+++ b/src/Record/MaxMind.php
@@ -8,12 +8,13 @@
* Contains data about your account.
*
* This record is returned by all location services and databases.
- *
- * @property-read int|null $queriesRemaining The number of remaining queries you
- * have for the service you are calling.
*/
class MaxMind implements \JsonSerializable
{
+ /**
+ * @var int|null the number of remaining queries you
+ * have for the service you are calling
+ */
public readonly ?int $queriesRemaining;
public function __construct(array $record)
diff --git a/src/Record/Postal.php b/src/Record/Postal.php
index d2e2e893..d3adac6f 100644
--- a/src/Record/Postal.php
+++ b/src/Record/Postal.php
@@ -9,19 +9,23 @@
*
* This record is returned by all location databases and services besides
* Country.
- *
- * @property-read string|null $code The postal code of the location. Postal codes
- * are not available for all countries. In some countries, this will only
- * contain part of the postal code. This attribute is returned by all location
- * databases and services besides Country.
- * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
- * confidence that the postal code is correct. This attribute is only
- * available from the Insights service and the GeoIP2 Enterprise
- * database.
*/
class Postal implements \JsonSerializable
{
+ /**
+ * @var string|null The postal code of the location. Postal codes
+ * are not available for all countries. In some countries, this will only
+ * contain part of the postal code. This attribute is returned by all location
+ * databases and services besides Country.
+ */
public readonly ?string $code;
+
+ /**
+ * @var int|null A value from 0-100 indicating MaxMind's
+ * confidence that the postal code is correct. This attribute is only
+ * available from the Insights service and the GeoIP2 Enterprise
+ * database.
+ */
public readonly ?int $confidence;
/**
diff --git a/src/Record/RepresentedCountry.php b/src/Record/RepresentedCountry.php
index 530f02c5..a810fc63 100644
--- a/src/Record/RepresentedCountry.php
+++ b/src/Record/RepresentedCountry.php
@@ -10,13 +10,14 @@
* This class contains the country-level data associated with an IP address
* for the IP's represented country. The represented country is the country
* represented by something like a military base.
- *
- * @property-read string|null $type A string indicating the type of entity that is
- * representing the country. Currently we only return military
- * but this could expand to include other types in the future.
*/
class RepresentedCountry extends Country
{
+ /**
+ * @var string|null A string indicating the type of entity that is
+ * representing the country. Currently we only return military
+ * but this could expand to include other types in the future.
+ */
public readonly ?string $type;
/**
diff --git a/src/Record/Subdivision.php b/src/Record/Subdivision.php
index 5489f981..cd11e58b 100644
--- a/src/Record/Subdivision.php
+++ b/src/Record/Subdivision.php
@@ -9,27 +9,15 @@
*
* This record is returned by all location databases and services besides
* Country.
- *
- * @property-read int|null $confidence This is a value from 0-100 indicating
- * MaxMind's confidence that the subdivision is correct. This attribute is
- * only available from the Insights service and the GeoIP2 Enterprise
- * database.
- * @property-read int|null $geonameId This is a GeoName ID for the subdivision.
- * This attribute is returned by all location databases and services besides
- * Country.
- * @property-read string|null $isoCode This is a string up to three characters long
- * contain the subdivision portion of the ISO 3166-2 code. See
- * https://en.wikipedia.org/wiki/ISO_3166-2. This attribute is returned by all
- * location databases and services except Country.
- * @property-read string|null $name The name of the subdivision based on the
- * locales list passed to the constructor. This attribute is returned by all
- * location databases and services besides Country.
- * @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
- * databases and services besides Country.
*/
class Subdivision extends AbstractPlaceRecord
{
+ /**
+ * @var string|null This is a string up to three characters long
+ * contain the subdivision portion of the ISO 3166-2 code. See
+ * https://en.wikipedia.org/wiki/ISO_3166-2. This attribute is returned by all
+ * location databases and services except Country.
+ */
public readonly ?string $isoCode;
/**
diff --git a/src/Record/Traits.php b/src/Record/Traits.php
index b6b4052a..5421b17a 100644
--- a/src/Record/Traits.php
+++ b/src/Record/Traits.php
@@ -10,135 +10,203 @@
* Contains data for the traits record associated with an IP address.
*
* This record is returned by all location services and databases.
- *
- * @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 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 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", and
- * "Satellite". Additional values may be added in the future. This attribute is
- * only available from the City Plus and Insights web services and the GeoIP2
- * Enterprise database.
- * @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 Plus and Insights web services and the GeoIP2 Enterprise
- * database.
- * @property-read string|null $ipAddress The IP address that the data in the model
- * is for. If you performed a "me" lookup against the web service, this
- * will be the externally routable IP address for the system the code is
- * running on. If the system is behind a NAT, this may differ from the IP
- * address locally assigned to it. This attribute is returned by all end
- * 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
- * Insights.
- * @property-read bool $isAnonymousProxy *Deprecated.* Please see our GeoIP2
- * Anonymous IP database
- * (https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine
- * whether the IP address is used by an anonymizing service.
- * @property-read bool $isAnonymousVpn This is true if the IP address is
- * 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 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 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 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 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 Insights.
- * @property-read string|null $isp The name of the ISP 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 $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 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 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
- * 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 Insights.
- * @property-read string|null $userType
The user type associated with the IP
- * address. This can be one of the following values:
- *
- *
business
- *
cafe
- *
cellular
- *
college
- *
consumer_privacy_network
- *
content_delivery_network
- *
dialup
- *
government
- *
hosting
- *
library
- *
military
- *
residential
- *
router
- *
school
- *
search_engine_spider
- *
traveler
- *
- *
- * This attribute is only available from the Insights web service and the
- * GeoIP2 Enterprise database.
- *
*/
class Traits implements \JsonSerializable
{
+ /**
+ * @var int|null 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 Plus and Insights web services and the
+ * GeoIP2 Enterprise database.
+ */
public readonly ?int $autonomousSystemNumber;
+
+ /**
+ * @var string|null 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 Plus and Insights web services and
+ * the GeoIP2 Enterprise database.
+ */
public readonly ?string $autonomousSystemOrganization;
+
+ /**
+ * @var string|null The connection type may take the
+ * following values: "Dialup", "Cable/DSL", "Corporate", "Cellular", and
+ * "Satellite". Additional values may be added in the future. This attribute is
+ * only available from the City Plus and Insights web services and the GeoIP2
+ * Enterprise database.
+ */
public readonly ?string $connectionType;
+
+ /**
+ * @var string|null 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 Plus and Insights web services and the GeoIP2 Enterprise
+ * database.
+ */
public readonly ?string $domain;
+
+ /**
+ * @var string|null The IP address that the data in the model
+ * is for. If you performed a "me" lookup against the web service, this
+ * will be the externally routable IP address for the system the code is
+ * running on. If the system is behind a NAT, this may differ from the IP
+ * address locally assigned to it. This attribute is returned by all end
+ * points.
+ */
public readonly ?string $ipAddress;
+
+ /**
+ * @var bool This is true if the IP address belongs to
+ * any sort of anonymous network. This property is only available from GeoIP2
+ * Insights.
+ */
public readonly bool $isAnonymous;
+
+ /**
+ * @var bool *Deprecated.* Please see our GeoIP2
+ * Anonymous IP database
+ * (https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine
+ * whether the IP address is used by an anonymizing service.
+ *
+ * @deprecated
+ */
public readonly bool $isAnonymousProxy;
+
+ /**
+ * @var bool This is true if the IP address is
+ * 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 Insights.
+ */
public readonly bool $isAnonymousVpn;
+
+ /**
+ * @var bool 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 Insights.
+ */
public readonly bool $isHostingProvider;
+
+ /**
+ * @var bool 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.
+ */
public readonly bool $isLegitimateProxy;
- public readonly ?string $isp;
+
+ /**
+ * @var bool This is true if the IP address belongs to
+ * a public proxy. This property is only available from GeoIP2 Insights.
+ */
public readonly bool $isPublicProxy;
+
+ /**
+ * @var bool 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 Insights.
+ */
public readonly bool $isResidentialProxy;
+
+ /**
+ * @var bool *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.
+ *
+ * @deprecated
+ */
public readonly bool $isSatelliteProvider;
+
+ /**
+ * @var bool This is true if the IP address is a Tor
+ * exit node. This property is only available from GeoIP2 Insights.
+ */
public readonly bool $isTorExitNode;
+
+ /**
+ * @var string|null The name of the ISP associated with the IP
+ * address. This attribute is only available from the City Plus and Insights
+ * web services and the GeoIP2 Enterprise database.
+ */
+ public readonly ?string $isp;
+
+ /**
+ * @var string|null 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.
+ */
public readonly ?string $mobileCountryCode;
+
+ /**
+ * @var string|null 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.
+ */
public readonly ?string $mobileNetworkCode;
+
+ /**
+ * @var string|null 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.
+ */
public readonly ?string $network;
+
+ /**
+ * @var string|null 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.
+ */
public readonly ?string $organization;
+
+ /**
+ * @var float|null An indicator of how static or
+ * dynamic an IP address is. This property is only available from GeoIP2
+ * Insights.
+ */
public readonly ?float $staticIpScore;
+
+ /**
+ * @var int|null 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 Insights.
+ */
public readonly ?int $userCount;
+
+ /**
+ * @var string|null
The user type associated with the IP
+ * address. This can be one of the following values:
+ *
+ *
business
+ *
cafe
+ *
cellular
+ *
college
+ *
consumer_privacy_network
+ *
content_delivery_network
+ *
dialup
+ *
government
+ *
hosting
+ *
library
+ *
military
+ *
residential
+ *
router
+ *
school
+ *
search_engine_spider
+ *
traveler
+ *
+ *
+ * This attribute is only available from the Insights web service and the
+ * GeoIP2 Enterprise database.
+ *
+ */
public readonly ?string $userType;
public function __construct(array $record)
From 59aab5da7de6ae5379bc4947069807ca16fe092e Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Tue, 31 Oct 2023 15:00:33 -0700
Subject: [PATCH 09/10] Remove deprecated properties
---
CHANGELOG.md | 2 ++
src/Record/Traits.php | 28 ------------------------
tests/GeoIp2/Test/Model/CountryTest.php | 7 ------
tests/GeoIp2/Test/Model/InsightsTest.php | 14 ------------
4 files changed, 2 insertions(+), 49 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f49667c..537221c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ CHANGELOG
classes rather than magic methods. This significantly improves performance.
* BREAKING: The `raw` property on model classess and the `record` property on
record classes have been removed.
+* BREAKING: On `GeoIp2\Record\Traits`, the deprecated `isAnonymousProxy` and
+ `isSatelliteProvider` properties have been removed.
* BREAKING: The `jsonSerialize` output has changed.
* `GeoIp2\WebService\Client` methods now throw an `InvalidArgumentException`
if an invalid IP address is passed to them. Previously, they would make
diff --git a/src/Record/Traits.php b/src/Record/Traits.php
index 5421b17a..5ffcb45d 100644
--- a/src/Record/Traits.php
+++ b/src/Record/Traits.php
@@ -66,16 +66,6 @@ class Traits implements \JsonSerializable
*/
public readonly bool $isAnonymous;
- /**
- * @var bool *Deprecated.* Please see our GeoIP2
- * Anonymous IP database
- * (https://www.maxmind.com/en/geoip2-anonymous-ip-database) to determine
- * whether the IP address is used by an anonymizing service.
- *
- * @deprecated
- */
- public readonly bool $isAnonymousProxy;
-
/**
* @var bool This is true if the IP address is
* registered to an anonymous VPN provider. If a VPN provider does not register
@@ -113,16 +103,6 @@ class Traits implements \JsonSerializable
*/
public readonly bool $isResidentialProxy;
- /**
- * @var bool *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.
- *
- * @deprecated
- */
- public readonly bool $isSatelliteProvider;
-
/**
* @var bool This is true if the IP address is a Tor
* exit node. This property is only available from GeoIP2 Insights.
@@ -217,14 +197,12 @@ public function __construct(array $record)
$this->domain = $record['domain'] ?? null;
$this->ipAddress = $record['ip_address'] ?? null;
$this->isAnonymous = $record['is_anonymous'] ?? false;
- $this->isAnonymousProxy = $record['is_anonymous_proxy'] ?? false;
$this->isAnonymousVpn = $record['is_anonymous_vpn'] ?? false;
$this->isHostingProvider = $record['is_hosting_provider'] ?? false;
$this->isLegitimateProxy = $record['is_legitimate_proxy'] ?? false;
$this->isp = $record['isp'] ?? null;
$this->isPublicProxy = $record['is_public_proxy'] ?? false;
$this->isResidentialProxy = $record['is_residential_proxy'] ?? false;
- $this->isSatelliteProvider = $record['is_satellite_provider'] ?? false;
$this->isTorExitNode = $record['is_tor_exit_node'] ?? false;
$this->mobileCountryCode = $record['mobile_country_code'] ?? null;
$this->mobileNetworkCode = $record['mobile_network_code'] ?? null;
@@ -261,9 +239,6 @@ public function jsonSerialize(): array
if ($this->isAnonymous !== false) {
$js['is_anonymous'] = $this->isAnonymous;
}
- if ($this->isAnonymousProxy !== false) {
- $js['is_anonymous_proxy'] = $this->isAnonymousProxy;
- }
if ($this->isAnonymousVpn !== false) {
$js['is_anonymous_vpn'] = $this->isAnonymousVpn;
}
@@ -279,9 +254,6 @@ public function jsonSerialize(): array
if ($this->isResidentialProxy !== false) {
$js['is_residential_proxy'] = $this->isResidentialProxy;
}
- if ($this->isSatelliteProvider !== false) {
- $js['is_satellite_provider'] = $this->isSatelliteProvider;
- }
if ($this->isTorExitNode !== false) {
$js['is_tor_exit_node'] = $this->isTorExitNode;
}
diff --git a/tests/GeoIp2/Test/Model/CountryTest.php b/tests/GeoIp2/Test/Model/CountryTest.php
index c8cf92fd..9f1bc77e 100644
--- a/tests/GeoIp2/Test/Model/CountryTest.php
+++ b/tests/GeoIp2/Test/Model/CountryTest.php
@@ -164,13 +164,6 @@ public function testValues(): void
$this->model->registeredCountry->name,
'registered_country name is Germany'
);
-
- foreach (['isAnonymousProxy', 'isSatelliteProvider'] as $meth) {
- $this->assertFalse(
- $this->model->traits->{$meth},
- "traits $meth returns 0 by default"
- );
- }
}
public function testJsonSerialize(): void
diff --git a/tests/GeoIp2/Test/Model/InsightsTest.php b/tests/GeoIp2/Test/Model/InsightsTest.php
index 39815073..15ced55c 100644
--- a/tests/GeoIp2/Test/Model/InsightsTest.php
+++ b/tests/GeoIp2/Test/Model/InsightsTest.php
@@ -75,13 +75,11 @@ public function testFull(): void
'domain' => 'example.com',
'ip_address' => '1.2.3.4',
'is_anonymous' => true,
- 'is_anonymous_proxy' => true,
'is_anonymous_vpn' => true,
'is_hosting_provider' => true,
'is_legitimate_proxy' => true,
'is_public_proxy' => true,
'is_residential_proxy' => true,
- 'is_satellite_provider' => true,
'is_tor_exit_node' => true,
'isp' => 'Comcast',
'mobile_country_code' => '310',
@@ -187,21 +185,11 @@ public function testFull(): void
'$model->traits->isResidentialProxy is true'
);
- $this->assertTrue(
- $model->traits->isSatelliteProvider,
- '$model->traits->isSatelliteProvider is true'
- );
-
$this->assertTrue(
$model->traits->isTorExitNode,
'$model->traits->isTorExitNode is true'
);
- $this->assertTrue(
- $model->traits->isAnonymousProxy,
- '$model->traits->isAnonymousProxy is true'
- );
-
$this->assertSame(
'310',
$model->traits->mobileCountryCode,
@@ -266,13 +254,11 @@ public function testFull(): void
'domain' => 'example.com',
'ip_address' => '1.2.3.4',
'is_anonymous' => true,
- 'is_anonymous_proxy' => true,
'is_anonymous_vpn' => true,
'is_hosting_provider' => true,
'is_legitimate_proxy' => true,
'is_public_proxy' => true,
'is_residential_proxy' => true,
- 'is_satellite_provider' => true,
'is_tor_exit_node' => true,
'isp' => 'Comcast',
'mobile_country_code' => '310',
From e1a926142ff98e59886a5c2c7e4007e3771be4e0 Mon Sep 17 00:00:00 2001
From: Gregory Oschwald
Date: Mon, 6 Nov 2023 14:56:04 -0800
Subject: [PATCH 10/10] Remove unused elements
---
phpunit.xml.dist | 6 ------
1 file changed, 6 deletions(-)
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 583a1a98..88df9f13 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -5,10 +5,4 @@
./tests/GeoIp2/Test/
-
-