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:20
created

FiftyOneDegreesCom::hydrateOperatingSystem()   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
                var_dump($prevEx);
128
                var_dump($ex);
129
                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...
130
            }
131
132
            throw $ex;
133
        }
134
135
        /*
136
         * no json returned?
137
         */
138
        $contentType = $response->getHeader('Content-Type');
139
        if (! isset($contentType[0]) || $contentType[0] != 'application/json; charset=utf-8') {
140
            throw new Exception\RequestException('Could not get valid "application/json; charset=utf-8" response from "' . $request->getUri() . '". Response is "' . $response->getBody()->getContents() . '"');
141
        }
142
143
        $content = json_decode($response->getBody()->getContents());
144
145
        /*
146
         * No result
147
         */
148
        if (isset($content->MatchMethod) && $content->MatchMethod == 'None') {
149
            throw new Exception\NoResultFoundException('No result found for user agent: ' . $userAgent);
150
        }
151
152
        /*
153
         * Missing data?
154
         */
155
        if (! $content instanceof stdClass || ! isset($content->Values)) {
156
            throw new Exception\RequestException('Could not get valid response from "' . $request->getUri() . '". Data is missing "' . $response->getBody()->getContents() . '"');
157
        }
158
159
        /*
160
         * Convert the values, to something useable
161
         */
162
        $values              = new \stdClass();
163
        $values->MatchMethod = $content->MatchMethod;
164
165
        foreach ($content->Values as $key => $value) {
166
            if (is_array($value) && count($value) === 1 && isset($value[0])) {
167
                $values->{$key} = $value[0];
168
            }
169
        }
170
171
        foreach ($values as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $values of type object<stdClass> is not traversable.
Loading history...
172
            if ($value === 'True') {
173
                $values->{$key} = true;
174
            } elseif ($value === 'False') {
175
                $values->{$key} = false;
176
            }
177
        }
178
179
        return $values;
180
    }
181
182
    /**
183
     *
184
     * @param Model\Bot $bot
185
     * @param stdClass  $resultRaw
186
     */
187
    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...
188
    {
189
        $bot->setIsBot(true);
190
    }
191
192
    /**
193
     *
194
     * @param Model\Browser $browser
195
     * @param stdClass      $resultRaw
196
     */
197
    private function hydrateBrowser(Model\Browser $browser, stdClass $resultRaw)
198
    {
199
        if (isset($resultRaw->BrowserName)) {
200
            $browser->setName($this->getRealResult($resultRaw->BrowserName));
201
        }
202
203
        if (isset($resultRaw->BrowserVersion)) {
204
            $browser->getVersion()->setComplete($this->getRealResult($resultRaw->BrowserVersion));
205
        }
206
    }
207
208
    /**
209
     *
210
     * @param Model\RenderingEngine $engine
211
     * @param stdClass              $resultRaw
212
     */
213
    private function hydrateRenderingEngine(Model\RenderingEngine $engine, stdClass $resultRaw)
214
    {
215
        if (isset($resultRaw->LayoutEngine)) {
216
            $engine->setName($this->getRealResult($resultRaw->LayoutEngine));
217
        }
218
    }
219
220
    /**
221
     *
222
     * @param Model\OperatingSystem $os
223
     * @param stdClass              $resultRaw
224
     */
225
    private function hydrateOperatingSystem(Model\OperatingSystem $os, stdClass $resultRaw)
226
    {
227
        if (isset($resultRaw->PlatformName)) {
228
            $os->setName($this->getRealResult($resultRaw->PlatformName));
229
        }
230
231
        if (isset($resultRaw->PlatformVersion)) {
232
            $os->getVersion()->setComplete($this->getRealResult($resultRaw->PlatformVersion));
233
        }
234
    }
235
236
    /**
237
     *
238
     * @param Model\Device $device
239
     * @param stdClass     $resultRaw
240
     */
241
    private function hydrateDevice(Model\Device $device, stdClass $resultRaw)
242
    {
243
        if (isset($resultRaw->HardwareVendor)) {
244
            $device->setBrand($this->getRealResult($resultRaw->HardwareVendor));
245
        }
246
        if (isset($resultRaw->HardwareFamily)) {
247
            $device->setModel($this->getRealResult($resultRaw->HardwareFamily));
248
        }
249
        if (isset($resultRaw->DeviceType)) {
250
            $device->setType($this->getRealResult($resultRaw->DeviceType));
251
        }
252
        if (isset($resultRaw->IsMobile)) {
253
            $device->setIsMobile($this->getRealResult($resultRaw->IsMobile));
254
        }
255
    }
256
257
    public function parse($userAgent, array $headers = [])
258
    {
259
        $resultRaw = $this->getResult($userAgent, $headers);
260
261
        /*
262
         * Hydrate the model
263
         */
264
        $result = new Model\UserAgent();
265
        $result->setProviderResultRaw($resultRaw);
266
267
        /*
268
         * Bot detection
269
         */
270
        if (isset($resultRaw->IsCrawler) && $resultRaw->IsCrawler === true) {
271
            $this->hydrateBot($result->getBot(), $resultRaw);
272
273
            return $result;
274
        }
275
276
        /*
277
         * hydrate the result
278
         */
279
        $this->hydrateBrowser($result->getBrowser(), $resultRaw);
280
        $this->hydrateRenderingEngine($result->getRenderingEngine(), $resultRaw);
281
        $this->hydrateOperatingSystem($result->getOperatingSystem(), $resultRaw);
282
        $this->hydrateDevice($result->getDevice(), $resultRaw);
283
284
        return $result;
285
    }
286
}
287