Geolocate   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 9
lcom 1
cbo 7
dl 0
loc 94
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getLocation() 0 4 1
A __construct() 0 9 2
A saveInSession() 0 6 1
B __invoke() 0 27 5
1
<?php
2
3
namespace Psr7Middlewares\Middleware;
4
5
use Psr7Middlewares\Utils;
6
use Psr\Http\Message\ServerRequestInterface;
7
use Psr\Http\Message\ResponseInterface;
8
use Geocoder\Geocoder;
9
use Geocoder\ProviderAggregator;
10
use Geocoder\Provider\FreeGeoIp;
11
use Geocoder\Model\AddressCollection;
12
use Ivory\HttpAdapter\FopenHttpAdapter;
13
use RuntimeException;
14
15
/**
16
 * Middleware to geolocate the client using the ip.
17
 */
18
class Geolocate
19
{
20
    use Utils\StorageTrait;
21
22
    const KEY = 'GEOLOCATE';
23
24
    /**
25
     * @var Geocoder
26
     */
27
    private $geocoder;
28
29
    /**
30
     * @var bool
31
     */
32
    private $saveInSession = false;
33
34
    /**
35
     * Returns the client location.
36
     *
37
     * @param ServerRequestInterface $request
38
     *
39
     * @return AddressCollection|null
40
     */
41
    public static function getLocation(ServerRequestInterface $request)
42
    {
43
        return self::getAttribute($request, self::KEY);
44
    }
45
46
    /**
47
     * Constructor. Set the geocoder instance.
48
     *
49
     * @param null|Geocoder $geocoder
50
     */
51
    public function __construct(Geocoder $geocoder = null)
52
    {
53
        if ($geocoder === null) {
54
            $geocoder = new ProviderAggregator();
55
            $geocoder->registerProvider(new FreeGeoIp(new FopenHttpAdapter()));
56
        }
57
58
        $this->geocoder = $geocoder;
59
    }
60
61
    /**
62
     * Wheter or not save the geolocation in a session variable.
63
     *
64
     * @param bool $save
65
     *
66
     * @return self
67
     */
68
    public function saveInSession($save = true)
69
    {
70
        $this->saveInSession = $save;
71
72
        return $this;
73
    }
74
75
    /**
76
     * Execute the middleware.
77
     *
78
     * @param ServerRequestInterface $request
79
     * @param ResponseInterface      $response
80
     * @param callable               $next
81
     *
82
     * @return ResponseInterface
83
     */
84
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
85
    {
86
        if (!self::hasAttribute($request, ClientIp::KEY)) {
87
            throw new RuntimeException('Geolocate middleware needs ClientIp executed before');
88
        }
89
90
        $ip = ClientIp::getIp($request);
91
92
        if ($ip !== null) {
93
            if ($this->saveInSession) {
94
                $ips = &self::getStorage($request, self::KEY);
95
96
                if (isset($ips[$ip])) {
97
                    $address = new AddressCollection($ips[$ip]);
98
                } else {
99
                    $address = $this->geocoder->geocode($ip);
100
                    $ips[$ip] = $address->all();
101
                }
102
            } else {
103
                $address = $this->geocoder->geocode($ip);
104
            }
105
106
            $request = self::setAttribute($request, self::KEY, $address);
107
        }
108
109
        return $next($request, $response);
110
    }
111
}
112