Skip to content

Commit e0e96c1

Browse files
committed
Add tests and DTO class for the api response
1 parent 056e77c commit e0e96c1

18 files changed

+512
-58
lines changed

.github/workflows/tests.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Tests
2+
3+
on: push
4+
5+
jobs:
6+
tests:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
fail-fast: true
10+
matrix:
11+
php: [8.2, 8.3]
12+
laravel: [10, 11]
13+
name: PHP:${{ matrix.php }} / Laravel:${{ matrix.laravel }}
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v3
17+
18+
- name: Setup PHP
19+
uses: shivammathur/setup-php@v2
20+
with:
21+
php-version: ${{ matrix.php }}
22+
extensions: dom, curl, libxml, mbstring, zip
23+
coverage: none
24+
25+
- name: Install dependencies
26+
run: |
27+
composer require "illuminate/contracts=^${{ matrix.laravel }}" --prefer-dist --no-interaction --no-update
28+
composer update --prefer-dist --no-interaction --no-progress
29+
30+
- name: Execute tests
31+
run: vendor/bin/pest

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,16 @@ protected $middleware = [
4444

4545
```php
4646
Route::get('/', function () {
47-
$ip = request()->get('abstract-ip-geolocation')['ip_address']
48-
// Or
49-
$ip = session()->get('abstract-ip-geolocation')['ip_address']
50-
$location = "The IP address " . $ip;
47+
$geolocation = session()->get('abstract-ip-geolocation')
48+
$location = "The IP address " . $geolocation->ipAddress;
5149
return view('index', ['location' => $location]);
5250
});
5351
```
5452

5553
Will return the following string to the `index` view:
5654

5755
```shell
58-
"The IP address 127.0.0.1."
56+
"The IP address 127.0.0.1"
5957
```
6058

6159
### Configuration

config/abstract-ip-geolocation.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
|--------------------------------------------------------------------------
1111
| API Key
1212
|--------------------------------------------------------------------------
13-
|
13+
| Your API token from abstractapi.com.
1414
|
1515
*/
1616

@@ -76,13 +76,16 @@
7676
'enable' => true,
7777

7878
/*
79-
|
79+
| This value is used to define the number of times a user's ip address can be stored,
80+
| if it has changed several times in the same session. Once this number has been reached,
81+
| the old values will be replaced.
8082
*/
8183

8284
'maxsize' => 5,
8385

8486
/*
85-
|
87+
| Time until cached value is no longer accessible
88+
| The default cached time is 24 hours (value).
8689
|
8790
*/
8891

src/AbstractIpGeolocation.php

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,46 @@
44

55
namespace Laravelcm\AbstractIpGeolocation;
66

7+
use Illuminate\Http\Request;
78
use Illuminate\Support\Facades\Http;
89
use Laravelcm\AbstractIpGeolocation\Exceptions\AbstractApiGeolocationException;
910

10-
final class AbstractIpGeolocation
11+
class AbstractIpGeolocation
1112
{
12-
public function __construct(
13-
public string $token,
14-
public ?string $fields = null,
15-
public ?DefaultCache $cache = null
16-
) {
13+
public ?DefaultCache $cache = null;
14+
15+
public ?string $token = null;
16+
17+
public ?string $fields = null;
18+
19+
public function __construct(public Request $request)
20+
{
21+
$this->token = config('abstract-ip-geolocation.api_key');
22+
$this->fields = config('abstract-ip-geolocation.fields');
23+
24+
if (config('abstract-ip-geolocation.cache.enable')) {
25+
$this->cache = new DefaultCache();
26+
}
27+
}
28+
29+
/**
30+
* @throws AbstractApiGeolocationException
31+
*/
32+
public function initialize(): array
33+
{
34+
$ipAddress = null;
35+
36+
if (config('abstract-ip-geolocation.include_ip')) {
37+
$ipAddress = (config('abstract-ip-geolocation.ip_selector', new IpSelector()))
38+
->getIp($this->request);
39+
}
40+
41+
return $this->details($ipAddress);
1742
}
1843

44+
/**
45+
* @throws AbstractApiGeolocationException
46+
*/
1947
public function details(?string $ipAddress = null): array
2048
{
2149
if ($this->cache) {
@@ -33,8 +61,8 @@ public function details(?string $ipAddress = null): array
3361
])
3462
->get('https://ipgeolocation.abstractapi.com/v1', [
3563
'api_key' => $this->token,
36-
'ip_address' => $ipAddress,
3764
'fields' => $this->fields,
65+
'ip_address' => $ipAddress,
3866
]);
3967
} catch (\Exception $e) {
4068
throw new AbstractApiGeolocationException($e->getMessage());

src/Contracts/CacheInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ public function has(string $name): bool;
1010

1111
public function get(string $name): mixed;
1212

13-
public function set(string $name, $value);
13+
public function set(string $name, $value): void;
1414
}

src/DataObject/Connection.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\DataObject;
6+
7+
final class Connection
8+
{
9+
public function __construct(
10+
public string $connectionType,
11+
public int $autonomousSystemNumber,
12+
public string $autonomousSystemOrganization,
13+
public string $ispName,
14+
public string $organizationName,
15+
) {
16+
}
17+
}

src/DataObject/Currency.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\DataObject;
6+
7+
final class Currency
8+
{
9+
public function __construct(
10+
public string $name,
11+
public string $code,
12+
) {
13+
}
14+
}

src/DataObject/Flag.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\DataObject;
6+
7+
final class Flag
8+
{
9+
public function __construct(
10+
public string $svg,
11+
public string $png,
12+
public string $emoji,
13+
public string $unicode,
14+
) {
15+
}
16+
}

src/DataObject/GeolocationData.php

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\DataObject;
6+
7+
final class GeolocationData
8+
{
9+
public ?string $ipAddress = null;
10+
11+
public ?string $city = null;
12+
13+
public ?int $cityGeonameId = null;
14+
15+
public ?string $region = null;
16+
17+
public ?string $regionIsoCode = null;
18+
19+
public ?int $regionGeonameId = null;
20+
21+
public ?string $postalCode = null;
22+
23+
public ?string $country = null;
24+
25+
public ?string $countryCode = null;
26+
27+
public ?bool $countryIsEU = null;
28+
29+
public ?string $continent = null;
30+
31+
public ?string $continentCode = null;
32+
33+
public ?int $continentGeonameId = null;
34+
35+
public ?float $longitude = null;
36+
37+
public ?float $latitude = null;
38+
39+
public ?Security $security = null;
40+
41+
public ?Timezone $timezone = null;
42+
43+
public ?Flag $flag = null;
44+
45+
public ?Currency $currency = null;
46+
47+
public ?Connection $connection = null;
48+
49+
public function __construct(
50+
?string $ipAddress = null,
51+
?string $city = null,
52+
?int $cityGeonameId = null,
53+
?string $region = null,
54+
?string $regionIsoCode = null,
55+
?int $regionGeonameId = null,
56+
?string $postalCode = null,
57+
?string $country = null,
58+
?string $countryCode = null,
59+
?bool $countryIsEU = null,
60+
?string $continent = null,
61+
?string $continentCode = null,
62+
?int $continentGeonameId = null,
63+
?float $longitude = null,
64+
?float $latitude = null,
65+
?Security $security = null,
66+
?Timezone $timezone = null,
67+
?Flag $flag = null,
68+
?Currency $currency = null,
69+
?Connection $connection = null,
70+
) {
71+
$this->ipAddress = $ipAddress;
72+
$this->city = $city;
73+
$this->cityGeonameId = $cityGeonameId;
74+
$this->regionIsoCode = $regionIsoCode;
75+
$this->regionGeonameId = $regionGeonameId;
76+
$this->postalCode = $postalCode;
77+
$this->region = $region;
78+
$this->country = $country;
79+
$this->countryCode = $countryCode;
80+
$this->countryIsEU = $countryIsEU;
81+
$this->continent = $continent;
82+
$this->continentCode = $continentCode;
83+
$this->continentGeonameId = $continentGeonameId;
84+
$this->longitude = $longitude;
85+
$this->latitude = $latitude;
86+
$this->security = $security;
87+
$this->timezone = $timezone;
88+
$this->flag = $flag;
89+
$this->currency = $currency;
90+
$this->connection = $connection;
91+
}
92+
93+
public static function fromResponse(array $data): GeolocationData
94+
{
95+
return new self(
96+
ipAddress: self::valueIfExist('ip_address', $data),
97+
city: self::valueIfExist('city', $data),
98+
cityGeonameId: self::valueIfExist('city_geoname_id', $data),
99+
region: self::valueIfExist('region', $data),
100+
regionIsoCode: self::valueIfExist('region_iso_code', $data),
101+
regionGeonameId: self::valueIfExist('region_geoname_id', $data),
102+
postalCode: self::valueIfExist('postal_code', $data),
103+
country: self::valueIfExist('country', $data),
104+
countryCode: self::valueIfExist('country_code', $data),
105+
countryIsEU: self::valueIfExist('country_is_eu', $data),
106+
continent: self::valueIfExist('continent', $data),
107+
continentCode: self::valueIfExist('continent', $data),
108+
continentGeonameId: self::valueIfExist('country_geoname_id', $data),
109+
longitude: self::valueIfExist('longitude', $data),
110+
latitude: self::valueIfExist('latitude', $data),
111+
security: array_key_exists('security', $data)
112+
? new Security(isVpn: $data['security']['is_vpn'])
113+
: null,
114+
timezone: array_key_exists('timezone', $data)
115+
? new Timezone(
116+
name: $data['timezone']['name'],
117+
abbreviation: $data['timezone']['abbreviation'],
118+
gmtOffset: $data['timezone']['gmt_offset'],
119+
currentTime: $data['timezone']['current_time'],
120+
isDST: $data['timezone']['is_dst'],
121+
)
122+
: null,
123+
flag: array_key_exists('flag', $data)
124+
? new Flag(
125+
svg: $data['flag']['svg'],
126+
png: $data['flag']['png'],
127+
emoji: $data['flag']['emoji'],
128+
unicode: $data['flag']['unicode'],
129+
)
130+
: null,
131+
currency: array_key_exists('currency', $data)
132+
? new Currency(
133+
name: $data['currency']['currency_name'],
134+
code: $data['currency']['currency_code']
135+
)
136+
: null,
137+
connection: array_key_exists('connection', $data)
138+
? new Connection(
139+
connectionType: $data['connection']['connection_type'],
140+
autonomousSystemNumber: $data['connection']['autonomous_system_number'],
141+
autonomousSystemOrganization: $data['connection']['autonomous_system_organization'],
142+
ispName: $data['connection']['isp_name'],
143+
organizationName: $data['connection']['organization_name'],
144+
)
145+
: null,
146+
);
147+
}
148+
149+
protected static function valueIfExist(string $key, array $data): mixed
150+
{
151+
return array_key_exists($key, $data) ? $data[$key] : null;
152+
}
153+
}

src/DataObject/Security.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\DataObject;
6+
7+
final class Security
8+
{
9+
public function __construct(public bool $isVpn)
10+
{
11+
}
12+
}

src/DataObject/Timezone.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\DataObject;
6+
7+
final class Timezone
8+
{
9+
public function __construct(
10+
public string $name,
11+
public string $abbreviation,
12+
public int $gmtOffset,
13+
public string $currentTime,
14+
public bool $isDST,
15+
) {
16+
}
17+
}

0 commit comments

Comments
 (0)