Skip to content

Commit 4013171

Browse files
committed
Initial commit
0 parents  commit 4013171

22 files changed

+594
-0
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 4
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*{.yml,.yaml,.json}]
15+
indent_size = 2

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: mckenziearts

.github/workflows/pint.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: pint
2+
3+
on: push
4+
5+
jobs:
6+
pint:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- name: Checkout code
11+
uses: actions/checkout@v3
12+
with:
13+
ref: ${{ github.head_ref }}
14+
- name: Set up PHP
15+
uses: shivammathur/setup-php@v2
16+
with:
17+
php-version: 8.3
18+
- name: Install Composer
19+
run: composer install --no-interaction
20+
- name: Run Laravel Pint
21+
run: composer pint
22+
- name: Commit changes
23+
uses: stefanzweifel/git-auto-commit-action@v4
24+
with:
25+
commit_message: Apply formatting

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/node_modules
2+
/vendor
3+
.idea
4+
.DS_Store
5+
composer.lock
6+
.phpunit.result.cache

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Arthur Monney
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# [<img src="https://assets-global.website-files.com/65166126ca18241731aa26b0/65390de624cb65770560dda5_FAV.png" alt="Abstract API" width="24"/>](https://www.abstractapi.com) Abstract’s IP Geolocation API Laravel Client Library
2+
3+
### Getting Started
4+
5+
Abstract’s IP Geolocation API is a fast, lightweight, modern, and RESTful JSON API for determining the location and other details of IP addresses from over 190 countries.
6+
7+
The free plan is limited to 1,000 requests per month. To enable all the data fields and additional request volumes see [https://www.abstractapi.com/api/ip-geolocation-api#pricing](https://www.abstractapi.com/api/ip-geolocation-api#pricing).
8+
9+
### Installation
10+
11+
The package works with PHP 8 and is available using [Composer](https://getcomposer.org).
12+
13+
```shell
14+
composer require laravelcm/abstract-ip-geolocation
15+
```
16+
17+
### Usage
18+
19+
Open your application's `\app\Http\Kernel.php` file and add the following to the `Kernel::middleware` property:
20+
21+
```php
22+
protected $middleware = [
23+
...
24+
\Laravelcm\AbstractIpGeolocation\Middleware\AbstractIpGeolocation::class,
25+
];
26+
```
27+
28+
#### Quick Start
29+
30+
```php
31+
Route::get('/', function () {
32+
$location = "The IP address " . request()->get('abstract-ip-geolocation')['ip_address'];
33+
return view('index', ['location' => $location]);
34+
});
35+
```
36+
37+
Will return the following string to the `index` view:
38+
39+
```shell
40+
"The IP address 127.0.0.1."
41+
```
42+
43+
### Configuration
44+
45+
wip..

composer.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"name": "laravelcm/abstract-ip-geolocation",
3+
"description": "Abstract’s IP Geolocation API is a fast, lightweight, modern, and RESTful JSON API for determining the location and other details of IP addresses from over 190 countries.",
4+
"license": "MIT",
5+
"keywords": [
6+
"laravel",
7+
"ip-geolocation",
8+
"abstract-api"
9+
],
10+
"authors": [
11+
{
12+
"name": "Arthur Monney",
13+
"email": "monneylobe@gmail.com"
14+
}
15+
],
16+
"require": {
17+
"php": "^8.2",
18+
"ext-json": "*",
19+
"illuminate/support": "^10.0|^11.0",
20+
"spatie/laravel-package-tools": "^1.15"
21+
},
22+
"require-dev": {
23+
"orchestra/testbench": "^8.5",
24+
"laravel/pint": "^1.1",
25+
"pestphp/pest": "^2.34",
26+
"mockery/mockery": "^1.6"
27+
},
28+
"autoload": {
29+
"psr-4": {
30+
"Laravelcm\\AbstractIpGeolocation\\": "src/"
31+
}
32+
},
33+
"autoload-dev": {
34+
"psr-4": {
35+
"Laravelcm\\AbstractIpGeolocation\\Tests\\": "tests/"
36+
}
37+
},
38+
"extra": {
39+
"laravel": {
40+
"providers": [
41+
"Laravelcm\\AbstractIpGeolocation\\AbstractIpGeolocationServiceProvider"
42+
]
43+
}
44+
},
45+
"scripts": {
46+
"test": "vendor/bin/pest",
47+
"pint": "vendor/bin/pint"
48+
},
49+
"minimum-stability": "dev",
50+
"prefer-stable": true,
51+
"config": {
52+
"allow-plugins": {
53+
"pestphp/pest-plugin": true
54+
}
55+
}
56+
}

config/abstract-ip-geolocation.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Laravelcm\AbstractIpGeolocation\IpSelector;
6+
7+
return [
8+
9+
/*
10+
|--------------------------------------------------------------------------
11+
| API Key
12+
|--------------------------------------------------------------------------
13+
|
14+
|
15+
*/
16+
17+
'api_key' => env('ABSTRACT_IP_GEOLOCATION_API_KEY'),
18+
19+
/*
20+
|--------------------------------------------------------------------------
21+
| User IP Address
22+
|--------------------------------------------------------------------------
23+
| By default, Abstract IP Geolocation will detect the ip address. But you can
24+
| update this configuration to include the client's ip address every time.
25+
|
26+
| If this value is set to "true", the ip will be detected using the "ip_selector" config.
27+
|
28+
*/
29+
30+
'include_ip' => false,
31+
32+
/*
33+
|--------------------------------------------------------------------------
34+
| Geolocation Fields
35+
|--------------------------------------------------------------------------
36+
| You can include a fields value in the query parameters with a comma
37+
| separated list of the top-level keys you want to be returned. For example
38+
| "fields => 'city,region'" will return only the city and region in the response.
39+
|
40+
| see: https://docs.abstractapi.com/ip-geolocation#request-parameters
41+
*/
42+
43+
'fields' => null,
44+
45+
/*
46+
|--------------------------------------------------------------------------
47+
| Ip Selector Class
48+
|--------------------------------------------------------------------------
49+
| You can select which class will be used to retrieve the client's ip address
50+
| or you can change it and use your own class to return the ip address.
51+
|
52+
| In case you use a custom IP selector, you may implement the
53+
| \Laravelcm\AbstractIpGeolocation\Contracts\AbstractIpInterface interface
54+
|
55+
| Available class: "IpSelector", "OriginatingIpSelector"
56+
|
57+
*/
58+
59+
'ip_selector' => new IpSelector(),
60+
61+
/*
62+
|--------------------------------------------------------------------------
63+
| Cache HTTP Request API
64+
|--------------------------------------------------------------------------
65+
|
66+
|
67+
*/
68+
69+
'cache' => [
70+
/*
71+
| By default, requests are cached to retrieve the user's ip.
72+
| If you use the "Free plan" option, caching can help you save
73+
| on requests to the Abstract IP Geolocation API.
74+
*/
75+
76+
'enable' => true,
77+
78+
/*
79+
|
80+
*/
81+
82+
'maxsize' => 5,
83+
84+
/*
85+
|
86+
|
87+
*/
88+
89+
'ttl' => 86400,
90+
],
91+
92+
];

phpunit.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
colors="true"
6+
>
7+
<testsuites>
8+
<testsuite name="Test Suite">
9+
<directory suffix="Test.php">./tests</directory>
10+
</testsuite>
11+
</testsuites>
12+
<source>
13+
<include>
14+
<directory suffix=".php">./src</directory>
15+
</include>
16+
</source>
17+
</phpunit>

pint.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"presets": "laravel",
3+
"rules": {
4+
"concat_space": {
5+
"spacing": "one"
6+
}
7+
}
8+
}

src/AbstractIpGeolocation.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation;
6+
7+
use Illuminate\Support\Facades\Http;
8+
use Laravelcm\AbstractIpGeolocation\Exceptions\AbstractApiGeolocationException;
9+
10+
final class AbstractIpGeolocation
11+
{
12+
public function __construct(
13+
public string $token,
14+
public ?string $fields = null,
15+
public ?DefaultCache $cache = null
16+
) {
17+
}
18+
19+
public function details(?string $ipAddress = null): array
20+
{
21+
if ($this->cache) {
22+
$cacheResponse = $this->cache->get($this->cacheKey($ipAddress ?? '-1'));
23+
24+
if ($cacheResponse !== null) {
25+
return $cacheResponse;
26+
}
27+
}
28+
29+
try {
30+
$response = Http::withHeaders([
31+
'content-type' => 'application/json',
32+
'accept' => 'application/json',
33+
])
34+
->get('https://ipgeolocation.abstractapi.com/v1', [
35+
'api_key' => $this->token,
36+
'ip_address' => $ipAddress,
37+
'fields' => $this->fields,
38+
]);
39+
} catch (\Exception $e) {
40+
throw new AbstractApiGeolocationException($e->getMessage());
41+
}
42+
43+
if ($response->status() === 422) {
44+
throw new AbstractApiGeolocationException('The request was aborted due to insufficient API credits. (Free plan)');
45+
} elseif ($response->status() >= 400) {
46+
throw new AbstractApiGeolocationException('Exception: ' . json_encode([
47+
'status' => $response->status(),
48+
'message' => $response->body(),
49+
]));
50+
}
51+
52+
$result = $response->json();
53+
54+
$this->cache?->set($this->cacheKey($ipAddress ?? '-1'), $result);
55+
56+
return $result;
57+
}
58+
59+
protected function cacheKey(string $key): string
60+
{
61+
return sprintf('%s_v%s', $key, '-1');
62+
}
63+
}
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;
6+
7+
use Spatie\LaravelPackageTools\Package;
8+
use Spatie\LaravelPackageTools\PackageServiceProvider;
9+
10+
final class AbstractIpGeolocationServiceProvider extends PackageServiceProvider
11+
{
12+
public function configurePackage(Package $package): void
13+
{
14+
$package->name('abstract-ip-geolocation')
15+
->hasConfigFile();
16+
}
17+
}

src/Contracts/AbstractIpInterface.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravelcm\AbstractIpGeolocation\Contracts;
6+
7+
interface AbstractIpInterface
8+
{
9+
/**
10+
* Get IP address of the current visitor.
11+
*
12+
* @param \Illuminate\Http\Request $request
13+
*/
14+
public function getIpAddress($request): string;
15+
}

0 commit comments

Comments
 (0)