Completed
Pull Request — master (#454)
by Alejandro
14:47
created

GeoLite2LocationResolver::resolveIpLocation()   A

Complexity

Conditions 3
Paths 5

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 3
nc 5
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\IpGeolocation\Resolver;
5
6
use GeoIp2\Database\Reader;
7
use GeoIp2\Exception\AddressNotFoundException;
8
use GeoIp2\Model\City;
9
use GeoIp2\Record\Subdivision;
10
use MaxMind\Db\Reader\InvalidDatabaseException;
11
use Shlinkio\Shlink\Common\Exception\WrongIpException;
12
use Shlinkio\Shlink\IpGeolocation\Model;
13
use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface;
14
15
use function Functional\first;
16
17
class GeoLite2LocationResolver implements IpLocationResolverInterface
18
{
19
    /** @var Reader */
20
    private $geoLiteDbReader;
21
22
    public function __construct(Reader $geoLiteDbReader)
23
    {
24
        $this->geoLiteDbReader = $geoLiteDbReader;
25
    }
26
27
    /**
28
     * @throws WrongIpException
29
     */
30
    public function resolveIpLocation(string $ipAddress): Model\Location
31
    {
32
        try {
33
            $city = $this->geoLiteDbReader->city($ipAddress);
34
            return $this->mapFields($city);
35
        } catch (AddressNotFoundException $e) {
36
            throw WrongIpException::fromIpAddress($ipAddress, $e);
37
        } catch (InvalidDatabaseException $e) {
38
            throw new WrongIpException('Provided GeoLite2 db file is invalid', 0, $e);
39
        }
40
    }
41
42
    private function mapFields(City $city): Model\Location
43
    {
44
        /** @var Subdivision $region */
45
        $region = first($city->subdivisions);
46
47
        return new Model\Location(
48
            $city->country->isoCode ?? '',
49
            $city->country->name ?? '',
50
            $region->name ?? '',
51
            $city->city->name ?? '',
52
            (float) ($city->location->latitude ?? ''),
53
            (float) ($city->location->longitude ?? ''),
54
            $city->location->timeZone ?? ''
55
        );
56
    }
57
}
58