GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#93)
by Martin
06:14
created

FiftyOneDegreesCom::hydrateBrowser()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 3
eloc 5
nc 4
nop 2
1
<?php
2
namespace UserAgentParser\Provider\Http;
3
4
use GuzzleHttp\Client;
5
use GuzzleHttp\Psr7\Request;
6
use stdClass;
7
use UserAgentParser\Exception;
8
use UserAgentParser\Model;
9
10
/**
11
 * Abstraction of neutrinoapi.com
12
 *
13
 * @author Martin Keckeis <[email protected]>
14
 * @license MIT
15
 * @see https://51degrees.com
16
 */
17
class FiftyOneDegreesCom extends AbstractHttpProvider
18
{
19
    /**
20
     * Name of the provider
21
     *
22
     * @var string
23
     */
24
    protected $name = 'FiftyOneDegreesCom';
25
26
    /**
27
     * Homepage of the provider
28
     *
29
     * @var string
30
     */
31
    protected $homepage = 'https://51degrees.com';
32
33
    protected $detectionCapabilities = [
34
35
        'browser' => [
36
            'name'    => true,
37
            'version' => true,
38
        ],
39
40
        'renderingEngine' => [
41
            'name'    => true,
42
            'version' => false,
43
        ],
44
45
        'operatingSystem' => [
46
            'name'    => true,
47
            'version' => true,
48
        ],
49
50
        'device' => [
51
            'model'    => true,
52
            'brand'    => true,
53
            'type'     => true,
54
            'isMobile' => true,
55
            'isTouch'  => false,
56
        ],
57
58
        'bot' => [
59
            'isBot' => true,
60
            'name'  => false,
61
            'type'  => false,
62
        ],
63
    ];
64
65
    protected $defaultValues = [
66
        'general' => [
67
            '/^Unknown$/i',
68
        ],
69
    ];
70
71
    private static $uri = 'https://cloud.51degrees.com/api/v1';
72
73
    private $apiKey;
74
75
    public function __construct(Client $client, $apiKey)
76
    {
77
        parent::__construct($client);
78
79
        $this->apiKey = $apiKey;
80
    }
81
82
    /**
83
     *
84
     * @param  string                     $userAgent
85
     * @param  array                      $headers
86
     * @return stdClass
87
     * @throws Exception\RequestException
88
     */
89
    protected function getResult($userAgent, array $headers)
90
    {
91
        /*
92
         * an empty UserAgent makes no sense
93
         */
94
        if ($userAgent == '') {
95
            throw new Exception\NoResultFoundException('No result found for user agent: ' . $userAgent);
96
        }
97
98
        $headers['User-Agent'] = $userAgent;
99
100
        $parameters = '/' . $this->apiKey;
101
        $parameters .= '/match?';
102
103
        $headerString = [];
104
        foreach ($headers as $key => $value) {
105
            $headerString[] = $key . '=' . rawurlencode($value);
106
        }
107
108
        $parameters .= implode('&', $headerString);
109
110
        $uri = self::$uri . $parameters;
111
112
        $request = new Request('GET', $uri);
113
114
        try {
115
            $response = $this->getResponse($request);
116
        } catch (Exception\RequestException $ex) {
117
            /* @var $prevEx \GuzzleHttp\Exception\ClientException */
118
            $prevEx = $ex->getPrevious();
119
120
            if ($prevEx->hasResponse() === true && $prevEx->getResponse()->getStatusCode() === 403) {
121
                var_dump($prevEx->getRequest());
0 ignored issues
show
Security Debugging Code introduced by
var_dump($prevEx->getRequest()); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
122
                exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method getResult() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
123
124
                throw new Exception\InvalidCredentialsException('Your API key "' . $this->apiKey . '" is not valid for ' . $this->getName(), null, $ex);
0 ignored issues
show
Unused Code introduced by
throw new \UserAgentPars...>getName(), null, $ex); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
125
            } elseif ($prevEx->hasResponse() !== true) {
126
                var_dump($prevEx->getRequest());
127
                exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method getResult() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
128
            }
129
130
            throw $ex;
131
        }
132
133
        /*
134
         * no json returned?
135
         */
136
        $contentType = $response->getHeader('Content-Type');
137
        if (! isset($contentType[0]) || $contentType[0] != 'application/json; charset=utf-8') {
138
            throw new Exception\RequestException('Could not get valid "application/json; charset=utf-8" response from "' . $request->getUri() . '". Response is "' . $response->getBody()->getContents() . '"');
139
        }
140
141
        $content = json_decode($response->getBody()->getContents());
142
143
        /*
144
         * No result
145
         */
146
        if (isset($content->MatchMethod) && $content->MatchMethod == 'None') {
147
            throw new Exception\NoResultFoundException('No result found for user agent: ' . $userAgent);
148
        }
149
150
        /*
151
         * Missing data?
152
         */
153
        if (! $content instanceof stdClass || ! isset($content->Values)) {
154
            throw new Exception\RequestException('Could not get valid response from "' . $request->getUri() . '". Data is missing "' . $response->getBody()->getContents() . '"');
155
        }
156
157
        /*
158
         * Convert the values, to something useable
159
         */
160
        $values              = new \stdClass();
161
        $values->MatchMethod = $content->MatchMethod;
162
163
        foreach ($content->Values as $key => $value) {
164
            if (is_array($value) && count($value) === 1 && isset($value[0])) {
165
                $values->{$key} = $value[0];
166
            }
167
        }
168
169
        foreach ($values as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $values of type object<stdClass> is not traversable.
Loading history...
170
            if ($value === 'True') {
171
                $values->{$key} = true;
172
            } elseif ($value === 'False') {
173
                $values->{$key} = false;
174
            }
175
        }
176
177
        return $values;
178
    }
179
180
    /**
181
     *
182
     * @param Model\Bot $bot
183
     * @param stdClass  $resultRaw
184
     */
185
    private function hydrateBot(Model\Bot $bot, stdClass $resultRaw)
0 ignored issues
show
Unused Code introduced by
The parameter $resultRaw is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
186
    {
187
        $bot->setIsBot(true);
188
    }
189
190
    /**
191
     *
192
     * @param Model\Browser $browser
193
     * @param stdClass      $resultRaw
194
     */
195
    private function hydrateBrowser(Model\Browser $browser, stdClass $resultRaw)
196
    {
197
        if (isset($resultRaw->BrowserName)) {
198
            $browser->setName($this->getRealResult($resultRaw->BrowserName));
199
        }
200
201
        if (isset($resultRaw->BrowserVersion)) {
202
            $browser->getVersion()->setComplete($this->getRealResult($resultRaw->BrowserVersion));
203
        }
204
    }
205
206
    /**
207
     *
208
     * @param Model\RenderingEngine $engine
209
     * @param stdClass              $resultRaw
210
     */
211
    private function hydrateRenderingEngine(Model\RenderingEngine $engine, stdClass $resultRaw)
212
    {
213
        if (isset($resultRaw->LayoutEngine)) {
214
            $engine->setName($this->getRealResult($resultRaw->LayoutEngine));
215
        }
216
    }
217
218
    /**
219
     *
220
     * @param Model\OperatingSystem $os
221
     * @param stdClass              $resultRaw
222
     */
223
    private function hydrateOperatingSystem(Model\OperatingSystem $os, stdClass $resultRaw)
224
    {
225
        if (isset($resultRaw->PlatformName)) {
226
            $os->setName($this->getRealResult($resultRaw->PlatformName));
227
        }
228
229
        if (isset($resultRaw->PlatformVersion)) {
230
            $os->getVersion()->setComplete($this->getRealResult($resultRaw->PlatformVersion));
231
        }
232
    }
233
234
    /**
235
     *
236
     * @param Model\Device $device
237
     * @param stdClass     $resultRaw
238
     */
239
    private function hydrateDevice(Model\Device $device, stdClass $resultRaw)
240
    {
241
        if (isset($resultRaw->HardwareVendor)) {
242
            $device->setBrand($this->getRealResult($resultRaw->HardwareVendor));
243
        }
244
        if (isset($resultRaw->HardwareFamily)) {
245
            $device->setModel($this->getRealResult($resultRaw->HardwareFamily));
246
        }
247
        if (isset($resultRaw->DeviceType)) {
248
            $device->setType($this->getRealResult($resultRaw->DeviceType));
249
        }
250
        if (isset($resultRaw->IsMobile)) {
251
            $device->setIsMobile($this->getRealResult($resultRaw->IsMobile));
252
        }
253
    }
254
255
    public function parse($userAgent, array $headers = [])
256
    {
257
        $resultRaw = $this->getResult($userAgent, $headers);
258
259
        /*
260
         * Hydrate the model
261
         */
262
        $result = new Model\UserAgent();
263
        $result->setProviderResultRaw($resultRaw);
264
265
        /*
266
         * Bot detection
267
         */
268
        if (isset($resultRaw->IsCrawler) && $resultRaw->IsCrawler === true) {
269
            $this->hydrateBot($result->getBot(), $resultRaw);
270
271
            return $result;
272
        }
273
274
        /*
275
         * hydrate the result
276
         */
277
        $this->hydrateBrowser($result->getBrowser(), $resultRaw);
278
        $this->hydrateRenderingEngine($result->getRenderingEngine(), $resultRaw);
279
        $this->hydrateOperatingSystem($result->getOperatingSystem(), $resultRaw);
280
        $this->hydrateDevice($result->getDevice(), $resultRaw);
281
282
        return $result;
283
    }
284
}
285