Test Failed
Push — master ( 5ce95a...cd83ee )
by Carsten
03:45 queued 10s
created

HttpClientLocationCreator::__invoke()   B

Complexity

Conditions 5
Paths 18

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 8.125

Importance

Changes 0
Metric Value
dl 0
loc 40
ccs 9
cts 18
cp 0.5
rs 8.9688
c 0
b 0
f 0
cc 5
nc 18
nop 1
crap 8.125
1
<?php
2
namespace Germania\ClientIpLocation;
3
4
use Psr\Http\Client\ClientInterface;
5
use Psr\Http\Client\ClientExceptionInterface;
6
use Psr\Http\Client\RequestExceptionInterface;
7
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\RequestFactoryInterface;
10
use Psr\Http\Message\ResponseInterface;
11
12
use Psr\Log\LoggerInterface;
13
use Psr\Log\NullLogger;
14
use Psr\Log\LogLevel;
15
use Psr\Log\LoggerAwareTrait;
16
17
class HttpClientLocationCreator
18
{
19 1
    use LoggerAwareTrait;
20
21
    /**
22
     * @var ClientInterface
23
     */
24
    protected $client;
25
26
27
    /**
28
     * @var RequestFactoryInterface
29
     */
30
    public $request_factory;
31
32
33
    /**
34
     * Geocoder API endpoint.
35
     *
36
     * @var string
37
     */
38
    public $api;
39
40
41
    /**
42
     * IP adress query parameter
43
     *
44
     * @var string
45
     */
46
    public $ip_var_name = "ip";
47
48
49
    /**
50
     * @var callable
51
     */
52
    public $response_decoder;
53
54
55
    /**
56
     * @var mixed
57
     */
58
    public $default_location;
59
60
61
    /**
62
     * @var string
63
     */
64
    protected $error_loglevel = LogLevel::ERROR;
65
66
67
    /**
68
     * @param string                  $api              Geocoder API endpoint
69
     * @param ClientInterface         $client           PSR-18 HTTP Client
70
     * @param RequestFactoryInterface $request_factory  PSR-17 Request factory
71
     * @param callable|null           $response_decoder Optional: PSR-7 Response decoder callable
72
     */
73 2
    public function __construct( string $api, ClientInterface $client, RequestFactoryInterface $request_factory, callable $response_decoder = null, LoggerInterface $logger = null)
74
    {
75 2
        $this->setApiEndpoint( $api )
76 2
             ->setClient($client)
77 2
             ->setRequestFactory($request_factory)
78 2
             ->setResponseDecoder($response_decoder)
79 2
             ->setLogger( $logger ?: new NullLogger);
80 2
    }
81
82
83
84
    /**
85
     * @param  string $client_ip Client IP address
86
     */
87 2
    public function __invoke( string $client_ip )
88
    {
89 2
        $request = $this->createRequest($client_ip);
90
91
        try {
92 2
            $response = $this->client->sendRequest( $request);
93 2
            $response_status = $response->getStatusCode();
94
95
            if ($response_status == 404) {
96
                $this->logger->log( $this->notfound_loglevel, "Could not determine client location, proceed with default location", [
0 ignored issues
show
Bug introduced by
The property notfound_loglevel does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
97
                    'request' => $request->getUri()->__toString(),
98
                    'responseStatus' => $response_status,
99
                    'apiEndpoint' => $this->api,
100
                    'clientIp' => $client_ip
101
                ]);
102
                return $this->default_location;
103
            }
104
105
            return $this->decodeResponse($response);
106
        }
107
        catch (\Throwable $e) {
108
            $response_status = (!empty($response) && $response instanceOf ResponseInterface)
109
                            ? $response->getStatusCode()
110
                            : null;
111
112
            $msg = sprintf("Exception caught in HttpClientLocationCreator: %s", $e->getMessage());
113
            $msg_location = sprintf("%s:%s", $e->getFile(), $e->getLine());
114
            $this->logger->log( $this->error_loglevel, $msg, [
115 4
                'type' => get_class($e),
116
                'code' => $e->getCode(),
117 4
                'request' => $request->getUri()->__toString(),
118 4
                'responseStatus' => $response_status,
119
                'location' => $msg_location,
120 4
                'apiEndpoint' => $this->api,
121
                'clientIp' => $client_ip
122 4
            ]);
123
124
            return $this->default_location;
125
        }
126
    }
127
128
129
130
    /**
131 4
     * @param  string $client_ip Client IP address
132
     * @return RequestInterface
133 4
     */
134 4
    public function createRequest( string $client_ip ) : RequestInterface
135 4
    {
136
        $client_ip_urlencoded = urlencode($client_ip);
137
        $query_parameter_field = "{{" . $this->ip_var_name . "}}";
138
139
        $api = str_replace($query_parameter_field, $client_ip_urlencoded, $this->api);
140
141
        return $this->request_factory->createRequest("GET", $api);
142
    }
143
144
145 2
146
    /**
147 2
     * @param  ResponseInterface $response
148 2
     * @return mixed
149
     */
150
    public function decodeResponse(ResponseInterface $response)
151
    {
152
        return $this->response_decoder
153
        ? ($this->response_decoder)($response)
154
        : json_decode($response->getBody(), "assoc");
155
    }
156
157
158 4
159
    /**
160 4
     * Sets the default location to return on error
161 4
     *
162
     * @param mixed $location
163
     */
164
    public function setDefaultLocation( $location ) : self
165
    {
166
        $this->default_location = $location;
167
        return $this;
168
    }
169
170
171 6
    /**
172
     * @param string $error_loglevel PSR-3 Loglevel name
173 6
     */
174 6
    public function setErrorLoglevel( string $error_loglevel ) {
175
        $this->error_loglevel = $error_loglevel;
176
        return $this;
177
    }
178
179
180
    /**
181
     * Sets the API endpoint
182
     *
183 4
     * @param string $api
184
     */
185 4
    public function setApiEndpoint( string $api ) : self
186 4
    {
187
        $this->api = $api;
188
        return $this;
189
    }
190
191
192
193
    /**
194
     * Sets the HTTP Client to use.
195 4
     *
196
     * @param ClientInterface $client
197 4
     */
198 4
    public function setClient( ClientInterface $client ) : self
199
    {
200
        $this->client = $client;
201
        return $this;
202
    }
203
204
205
    /**
206
     * Sets the PSR-17 Request factory
207
     *
208
     * @param RequestFactoryInterface $request_factory
209
     */
210
    public function setRequestFactory( RequestFactoryInterface $request_factory ) : self
211
    {
212
        $this->request_factory = $request_factory;
213
        return $this;
214
    }
215
216
217
    /**
218
     * Sets the PSR-7 Response decoder callable.
219
     *
220
     * @param callable $response_decoder
221
     */
222
    public function setResponseDecoder( callable $response_decoder = null ) : self
223
    {
224
        $this->response_decoder = $response_decoder;
225
        return $this;
226
    }
227
228
}
229