Passed
Push — master ( 7e2fb1...68cb95 )
by Christian
01:58
created

IP::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
nc 1
nop 2
dl 0
loc 4
c 1
b 0
f 0
cc 1
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Faxity\DI;
4
5
use Anax\Commons\ContainerInjectableInterface;
6
use Anax\Commons\ContainerInjectableTrait;
7
use Faxity\Fetch\Fetch;
8
9
/**
10
 * DI module for validating & geo-locating IP addresses
11
 */
12
class IP implements ContainerInjectableInterface
13
{
14
    use ContainerInjectableTrait;
15
16
    /** The base URL of ipstack's api. */
17
    private const IPSTACK_URL = "http://api.ipstack.com";
18
19
    /**
20
     * @var string $accessKey The ipstack access key.
21
     * @var Fetch $http The http fetch client
22
     */
23
    private $accessKey;
24
    private $http;
25
26
27
    /**
28
     * @param string $accessKey access key to ipstacks API
29
     * @param Fetch|null $fetch Fetch client (optional)
30
     */
31 14
    public function __construct(string $accessKey, ?Fetch $fetch = null)
32
    {
33 14
        $this->accessKey = $accessKey;
34 14
        $this->http = $fetch ?? new Fetch();
35 14
    }
36
37
38
    /**
39
     * Gets the IP address of the client
40
     *
41
     * @return string
42
     */
43 2
    public function getAddress() : string
44
    {
45 2
        return $_SERVER["REMOTE_ADDR"] ?? "";
46
    }
47
48
49
    /**
50
     * Locates an ip address
51
     * @param string|null $ip IP address to locate
52
     *
53
     * @return array|null
54
     */
55 4
    public function locate(?string $ip) : ?array
56
    {
57
        // Check if ip is valid and not empty
58 4
        if (filter_var($ip, FILTER_VALIDATE_IP) == $ip) {
59 3
            $params = [ "access_key" => $this->accessKey ];
60 3
            $res = $this->http->get(self::IPSTACK_URL . "/$ip", $params);
61
62 3
            if (isset($res->latitude, $res->longitude)) {
63 1
                return [ $res->latitude, $res->longitude ];
64
            }
65
        }
66
67 3
        return null;
68
    }
69
70
71
    /**
72
     * Validate IP address and get info about the domain, null is returned if empty
73
     * @param string|null $ip IP to Validate
74
     *
75
     * @return object|null
76
     */
77 9
    public function validate(?string $ip) : ?object
78
    {
79 9
        if (empty($ip)) {
80 2
            return null;
81
        }
82
83
        $data = (object) [
84 7
            "ip" => $ip,
85
            "valid" => false,
86
            "type" => null,
87
            "domain" => null,
88
            "region" => null,
89
            "country" => null,
90
            "location" => null,
91
        ];
92
93
        // Check which protocol the address uses
94 7
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
95 2
            $data->type = "ipv4";
96 2
            $data->valid = true;
97 5
        } else if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
98 3
            $data->type = "ipv6";
99 3
            $data->valid = true;
100
        }
101
102 7
        if ($data->valid) {
103 5
            $res = $this->http->get(self::IPSTACK_URL . "/$ip", [
104 5
                "access_key" => $this->accessKey,
105
            ]);
106 5
            $host = gethostbyaddr($ip);
107 5
            $data->domain = $host != $ip ? $host : null;
108 5
            $data->region = $res->region_name ?? null;
109 5
            $data->country = $res->country_name ?? null;
110
111 5
            if (isset($res->latitude, $res->longitude)) {
112 2
                $data->location = (object) [
113 2
                    "latitude" => $res->latitude,
114 2
                    "longitude" => $res->longitude,
115
                ];
116
            }
117
        }
118
119 7
        return $data;
120
    }
121
}
122