Skip to content

Commit

Permalink
Merge pull request #217 from maxmind/greg/readonly-properties
Browse files Browse the repository at this point in the history
Use readonly properties for model classes
  • Loading branch information
faktas2 authored Nov 6, 2023
2 parents b76c914 + e1a9261 commit 441034b
Show file tree
Hide file tree
Showing 31 changed files with 1,159 additions and 834 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ CHANGELOG
3.0.0
-------------------

* IMPORTANT: PHP 8.0 or greater is now required.
* 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: 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
a request to the web service and throw a
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "^10.0",
"squizlabs/php_codesniffer": "3.*",
"phpstan/phpstan": "*"
},
Expand Down
24 changes: 6 additions & 18 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit bootstrap="./tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="GeoIP2 Test Suite">
<directory suffix="Test.php">./tests/GeoIp2/Test/</directory>
</testsuite>
</testsuites>

<filter>
<whitelist>
<directory suffix=".php">./src/GeoIp2/</directory>
</whitelist>
</filter>

<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="./vendor/autoload.php" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd" cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="GeoIP2 Test Suite">
<directory suffix="Test.php">./tests/GeoIp2/Test/</directory>
</testsuite>
</testsuites>
</phpunit>
13 changes: 2 additions & 11 deletions src/Database/Reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -84,7 +83,6 @@ public function __construct(
*/
public function city(string $ipAddress): City
{
// @phpstan-ignore-next-line
return $this->modelFor(City::class, 'City', $ipAddress);
}

Expand All @@ -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);
}

Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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);
}

Expand All @@ -212,15 +204,14 @@ public function enterprise(string $ipAddress): Enterprise
*/
public function isp(string $ipAddress): Isp
{
// @phpstan-ignore-next-line
return $this->flatModelFor(
Isp::class,
'GeoIP2-ISP',
$ipAddress
);
}

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);

Expand All @@ -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);

Expand Down
68 changes: 0 additions & 68 deletions src/Model/AbstractModel.php

This file was deleted.

125 changes: 86 additions & 39 deletions src/Model/AnonymousIp.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,100 @@

/**
* 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 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;
/**
* @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;

/**
* @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
{
$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;
}
}
Loading

0 comments on commit 441034b

Please sign in to comment.