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/ + + + + + + ./src/GeoIp2/ + + 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/
- - - - ./src/GeoIp2/ - -