Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/location.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@
'token' => env('IP2LOCATIONIO_TOKEN'),
],

'ipgeolocation' => [
'token' => env('IPGEOLOCATION_TOKEN'),
],

/*
|--------------------------------------------------------------------------
| Kloudend ~ ipapi.co Configuration
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ Available drivers:
- [MaxMind](https://www.maxmind.com/en/home)
- [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-IP-geolocation)
- [IP2Location.io](https://www.ip2location.io/)
- [IPGeolocation.io](https://ipgeolocation.io)

#### Setting up MaxMind with a self-hosted database (optional)

Expand Down
41 changes: 41 additions & 0 deletions src/Drivers/IpGeolocation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Stevebauman\Location\Drivers;

use Illuminate\Support\Fluent;
use Stevebauman\Location\Position;

class IpGeolocation extends HttpDriver
{
/**
* {@inheritdoc}
*/
public function url(string $ip): string
{
return 'https://api.ipgeolocation.io/v3/ipgeo?'.http_build_query([
'apiKey' => config('location.ipgeolocation.token'),
'ip' => $ip,
'fields' => 'location,currency.code,time_zone.name',
]);
}

/**
* {@inheritdoc}
*/
protected function hydrate(Position $position, Fluent $location): Position
{
$position->countryName = $location['location']['country_name'] ?? null;
$position->countryCode = $location['location']['country_code2'] ?? null;
$position->regionCode = $location['location']['state_code'] ?? null;
$position->regionName = $location['location']['state_prov'] ?? null;
$position->cityName = $location['location']['city'] ?? null;
$position->zipCode = $location['location']['zipcode'] ?? null;
$position->postalCode = $location['location']['zipcode'] ?? null;
$position->latitude = $location['location']['latitude'] ?? null;
$position->longitude = $location['location']['longitude'] ?? null;
$position->timezone = $location['time_zone']['name'] ?? null;
$position->currencyCode = $location['currency']['code'] ?? null;

return $position;
}
}
81 changes: 81 additions & 0 deletions tests/Drivers/IpGeolocationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

namespace Stevebauman\Location\Tests\Drivers;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Fluent;
use Mockery as m;
use Stevebauman\Location\Drivers\IpGeolocation;
use Stevebauman\Location\Facades\Location;
use Stevebauman\Location\Position;

it('it can process fluent response', function () {
$driver = m::mock(IpGeolocation::class)->makePartial();

$response = new Fluent([
'ip' => '66.102.0.0',
'location' => [
'continent_code' => 'NA',
'continent_name' => 'North America',
'country_code2' => 'US',
'country_code3' => 'USA',
'country_name' => 'United States',
'state_prov' => 'California',
'state_code' => 'US-CA',
'district' => 'Santa Clara County',
'city' => 'Mountain View',
'zipcode' => '94043',
'latitude' => '37.42240',
'longitude' => '-122.08421',
],
'currency' => ['code' => 'USD'],
'time_zone' => ['name' => 'America/Los_Angeles'],
]);

$driver
->shouldAllowMockingProtectedMethods()
->shouldReceive('process')->once()->andReturn($response);

Location::setDriver($driver);

$position = Location::get();

expect($position)->toBeInstanceOf(Position::class);

expect($position->toArray())->toEqual([
'countryName' => 'United States',
'currencyCode' => 'USD',
'countryCode' => 'US',
'regionCode' => 'US-CA',
'regionName' => 'California',
'cityName' => 'Mountain View',
'zipCode' => '94043',
'isoCode' => null,
'postalCode' => '94043',
'latitude' => '37.42240',
'longitude' => '-122.08421',
'metroCode' => null,
'areaCode' => null,
'ip' => '66.102.0.0',
'timezone' => 'America/Los_Angeles',
'driver' => get_class($driver),
]);
});

it('requests the v3 endpoint with the api key and a field filter', function () {
config(['location.ipgeolocation.token' => 'secret']);

expect((new IpGeolocation)->url('2001:4860:4860::8888'))->toBe(
'https://api.ipgeolocation.io/v3/ipgeo?apiKey=secret&ip=2001%3A4860%3A4860%3A%3A8888&fields=location%2Ccurrency.code%2Ctime_zone.name'
);
});

it('returns false when the api responds with an error', function () {
Http::fake([
'api.ipgeolocation.io/*' => Http::response(['message' => "'10.0.0.1' is a bogon IP address."], 423),
]);

Location::setDriver(new IpGeolocation);

expect(Location::get('10.0.0.1'))->toBeFalse();
});