Completed
Push — master ( 1b2d0a...89ea1a )
by Oscar
03:00
created

Geolocate::toSession()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 5
nc 2
nop 3
1
<?php
2
3
namespace Psr7Middlewares\Middleware;
4
5
use Psr7Middlewares\Middleware;
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
    const KEY = 'GEOLOCATE';
21
22
    /**
23
     * @var Geocoder
24
     */
25
    private $geocoder;
26
27
    /**
28
     * @var bool
29
     */
30
    private $saveInSession = false;
31
32
    /**
33
     * Returns the client location.
34
     *
35
     * @param ServerRequestInterface $request
36
     *
37
     * @return AddressCollection|null
38
     */
39
    public static function getLocation(ServerRequestInterface $request)
40
    {
41
        return Middleware::getAttribute($request, self::KEY);
42
    }
43
44
    /**
45
     * Constructor. Set the geocoder instance.
46
     *
47
     * @param null|Geocoder $geocoder
48
     */
49
    public function __construct(Geocoder $geocoder = null)
50
    {
51
        if ($geocoder === null) {
52
            $geocoder = new ProviderAggregator();
53
            $geocoder->registerProvider(new FreeGeoIp(new FopenHttpAdapter()));
54
        }
55
56
        $this->geocoder = $geocoder;
57
    }
58
59
    /**
60
     * Wheter or not save the geolocation in a session variable
61
     * 
62
     * @param bool $save
63
     * 
64
     * @return self
65
     */
66
    public function saveInSession($save = true)
67
    {
68
        $this->saveInSession = $save;
69
70
        return $this;
71
    }
72
73
    /**
74
     * Execute the middleware.
75
     *
76
     * @param ServerRequestInterface $request
77
     * @param ResponseInterface      $response
78
     * @param callable               $next
79
     *
80
     * @return ResponseInterface
81
     */
82
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
83
    {
84
        if (!Middleware::hasAttribute($request, ClientIp::KEY)) {
85
            throw new RuntimeException('Geolocate middleware needs ClientIp executed before');
86
        }
87
88
        if ($this->saveInSession && !Middleware::hasAttribute($request, Middleware::STORAGE_KEY)) {
89
            throw new RuntimeException('Csrf middleware needs a storage defined');
90
        }
91
92
        $ip = ClientIp::getIp($request);
93
94
        if ($ip !== null) {
95
            if (!$this->saveInSession || ($address = self::fromSession($request, $ip)) === null) {
96
                $address = $this->geocoder->geocode($ip);
97
            }
98
99
            $request = Middleware::setAttribute($request, self::KEY, $address);
100
101
            if ($this->saveInSession) {
102
                self::toSession($request, $ip, $address);
103
            }
104
        }
105
106
        return $next($request, $response);
107
    }
108
109
    /**
110
     * Returns the geolocation from the session storage
111
     * 
112
     * @param ResponseInterface      $response
0 ignored issues
show
Bug introduced by
There is no parameter named $response. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
113
     * @param string $ip
114
     * 
115
     * @return AddressCollection|null
116
     */
117
    static private function fromSession(ServerRequestInterface $request, $ip)
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
118
    {
119
        $storage = Middleware::getAttribute($request, Middleware::STORAGE_KEY);
120
        $ips = $storage->get(self::KEY);
121
122
        if (isset($ips[$ip])) {
123
            return new AddressCollection($ips[$ip]);
124
        }
125
    }
126
127
    /**
128
     * Saves the geolocation in the session storage
129
     * 
130
     * @param ResponseInterface      $response
0 ignored issues
show
Bug introduced by
There is no parameter named $response. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
131
     * @param string $ip
132
     * @param AddressCollection $address
133
     */
134
    static private function toSession(ServerRequestInterface $request, $ip, AddressCollection $address)
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
135
    {
136
        $storage = Middleware::getAttribute($request, Middleware::STORAGE_KEY);
137
        $ips = $storage->get(self::KEY) ?: [];
138
        $ips[$ip] = $address->all();
139
        $storage->set(self::KEY, $ips);
140
    }
141
}
142