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
Push — master ( 5e23db...89bf96 )
by Martin
17:15 queued 04:42
created

WhatIsMyBrowserCom   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 269
Duplicated Lines 16.73 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 52
c 5
b 0
f 1
lcom 1
cbo 13
dl 45
loc 269
ccs 87
cts 87
cp 1
rs 7.9487

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getVersion() 0 4 1
A __construct() 0 6 1
C getResult() 12 68 17
C hasResult() 0 24 11
B hydrateBrowser() 0 10 5
B hydrateRenderingEngine() 3 10 5
B hydrateOperatingSystem() 0 10 5
B hydrateDevice() 3 10 5
B parse() 27 27 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WhatIsMyBrowserCom often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WhatIsMyBrowserCom, and based on these observations, apply Extract Interface, too.

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
 *
12
 * @see https://developers.whatismybrowser.com/reference
13
 */
14
class WhatIsMyBrowserCom extends AbstractHttpProvider
15
{
16
    /**
17
     * Name of the provider
18
     *
19
     * @var string
20
     */
21
    protected $name = 'WhatIsMyBrowserCom';
22
23
    /**
24
     * Homepage of the provider
25
     *
26
     * @var string
27
     */
28
    protected $homepage = 'https://www.whatismybrowser.com/';
29
30
    protected $detectionCapabilities = [
31
32
        'browser' => [
33
            'name'    => true,
34
            'version' => true,
35
        ],
36
37
        'renderingEngine' => [
38
            'name'    => true,
39
            'version' => true,
40
        ],
41
42
        'operatingSystem' => [
43
            'name'    => true,
44
            'version' => true,
45
        ],
46
47
        'device' => [
48
            'model' => true,
49
            'brand' => true,
50
51
            'type'     => false,
52
            'isMobile' => false,
53
            'isTouch'  => false,
54
        ],
55
56
        'bot' => [
57
            'isBot' => false,
58
            'name'  => false,
59
            'type'  => false,
60
        ],
61
    ];
62
63
    protected $defaultValues = [
64
        'Unknown Mobile Browser',
65
        'Unknown browser',
66
    ];
67
68
    private static $uri = 'http://api.whatismybrowser.com/api/v1/user_agent_parse';
69
70
    private $apiKey;
71
72 19
    public function __construct(Client $client, $apiKey)
73
    {
74 19
        parent::__construct($client);
75
76 19
        $this->apiKey = $apiKey;
77 19
    }
78
79 1
    public function getVersion()
80
    {
81 1
        return;
82
    }
83
84
    /**
85
     *
86
     * @param  string                     $userAgent
87
     * @param  array                      $headers
88
     * @return stdClass
89
     * @throws Exception\RequestException
90
     */
91 14
    protected function getResult($userAgent, array $headers)
0 ignored issues
show
Unused Code introduced by
The parameter $headers 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...
92
    {
93
        /*
94
         * an empty UserAgent makes no sense
95
         */
96 14
        if ($userAgent == '') {
97 1
            throw new Exception\NoResultFoundException('No result found for user agent: ' . $userAgent);
98
        }
99
100
        $params = [
101 13
            'user_key'   => $this->apiKey,
102 13
            'user_agent' => $userAgent,
103 13
        ];
104
105 13
        $body = http_build_query($params, null, '&');
106
107 13
        $request = new Request('POST', self::$uri, [], $body);
108
109 13
        $response = $this->getResponse($request);
110
111
        /*
112
         * no json returned?
113
         */
114 13
        $contentType = $response->getHeader('Content-Type');
115 13 View Code Duplication
        if (! isset($contentType[0]) || $contentType[0] != 'application/json') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116 1
            throw new Exception\RequestException('Could not get valid "application/json" response from "' . $request->getUri() . '". Response is "' . $response->getBody()->getContents() . '"');
117
        }
118
119 12
        $content = json_decode($response->getBody()->getContents());
120
121
        /*
122
         * No result
123
         */
124 12
        if (isset($content->message_code) && $content->message_code == 'no_user_agent') {
125 1
            throw new Exception\NoResultFoundException('No result found for user agent: ' . $userAgent);
126
        }
127
128
        /*
129
         * Limit exceeded
130
         */
131 11 View Code Duplication
        if (isset($content->message_code) && $content->message_code == 'usage_limit_exceeded') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
132 1
            throw new Exception\LimitationExceededException('Exceeded the maximum number of request with API key "' . $this->apiKey . '" for ' . $this->getName());
133
        }
134
135
        /*
136
         * Error
137
         */
138 10
        if (isset($content->message_code) && $content->message_code == 'no_api_user_key') {
139 1
            throw new Exception\InvalidCredentialsException('Missing API key for ' . $this->getName());
140
        }
141
142 9 View Code Duplication
        if (isset($content->message_code) && $content->message_code == 'user_key_invalid') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143 1
            throw new Exception\InvalidCredentialsException('Your API key "' . $this->apiKey . '" is not valid for ' . $this->getName());
144
        }
145
146 8 View Code Duplication
        if (!isset($content->result) || $content->result !== 'success') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147 1
            throw new Exception\RequestException('Could not get valid response from "' . $request->getUri() . '". Response is "' . $response->getBody()->getContents() . '"');
148
        }
149
150
        /*
151
         * Missing data?
152
         */
153 7
        if (! $content instanceof stdClass || ! isset($content->parse) || ! $content->parse instanceof stdClass) {
154 1
            throw new Exception\RequestException('Could not get valid response from "' . $request->getUri() . '". Response is "' . print_r($content, true) . '"');
155
        }
156
157 6
        return $content->parse;
158
    }
159
160
    /**
161
     *
162
     * @param stdClass $resultRaw
163
     *
164
     * @return bool
165
     */
166 6
    private function hasResult(stdClass $resultRaw)
167
    {
168 6
        if (isset($resultRaw->browser_name) && $this->isRealResult($resultRaw->browser_name) === true) {
169 1
            return true;
170
        }
171
172 5
        if (isset($resultRaw->layout_engine_name) && $this->isRealResult($resultRaw->layout_engine_name) === true) {
173 1
            return true;
174
        }
175
176 4
        if (isset($resultRaw->operating_system_name) && $this->isRealResult($resultRaw->operating_system_name) === true) {
177 1
            return true;
178
        }
179
180 3
        if (isset($resultRaw->operating_platform) && $this->isRealResult($resultRaw->operating_platform) === true) {
181 1
            return true;
182
        }
183
184 2
        if (isset($resultRaw->operating_platform_vendor_name) && $this->isRealResult($resultRaw->operating_platform_vendor_name) === true) {
185 1
            return true;
186
        }
187
188 1
        return false;
189
    }
190
191
    /**
192
     *
193
     * @param Model\Browser $browser
194
     * @param stdClass      $resultRaw
195
     */
196 5
    private function hydrateBrowser(Model\Browser $browser, stdClass $resultRaw)
197
    {
198 5
        if (isset($resultRaw->browser_name) && $this->isRealResult($resultRaw->browser_name) === true) {
199 1
            $browser->setName($resultRaw->browser_name);
200 1
        }
201
202 5
        if (isset($resultRaw->browser_version_full) && $this->isRealResult($resultRaw->browser_version_full) === true) {
203 1
            $browser->getVersion()->setComplete($resultRaw->browser_version_full);
204 1
        }
205 5
    }
206
207
    /**
208
     *
209
     * @param Model\RenderingEngine $engine
210
     * @param stdClass              $resultRaw
211
     */
212 5
    private function hydrateRenderingEngine(Model\RenderingEngine $engine, stdClass $resultRaw)
213
    {
214 5 View Code Duplication
        if (isset($resultRaw->layout_engine_name) && $this->isRealResult($resultRaw->layout_engine_name) === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
215 1
            $engine->setName($resultRaw->layout_engine_name);
216 1
        }
217
218 5
        if (isset($resultRaw->layout_engine_version) && $this->isRealResult($resultRaw->layout_engine_version) === true) {
219 1
            $engine->getVersion()->setComplete($resultRaw->layout_engine_version);
220 1
        }
221 5
    }
222
223
    /**
224
     *
225
     * @param Model\OperatingSystem $os
226
     * @param stdClass              $resultRaw
227
     */
228 5
    private function hydrateOperatingSystem(Model\OperatingSystem $os, stdClass $resultRaw)
229
    {
230 5
        if (isset($resultRaw->operating_system_name) && $this->isRealResult($resultRaw->operating_system_name) === true) {
231 1
            $os->setName($resultRaw->operating_system_name);
232 1
        }
233
234 5
        if (isset($resultRaw->operating_system_version_full) && $this->isRealResult($resultRaw->operating_system_version_full) === true) {
235 1
            $os->getVersion()->setComplete($resultRaw->operating_system_version_full);
236 1
        }
237 5
    }
238
239
    /**
240
     *
241
     * @param Model\UserAgent $device
242
     * @param stdClass        $resultRaw
243
     */
244 5
    private function hydrateDevice(Model\Device $device, stdClass $resultRaw)
245
    {
246 5 View Code Duplication
        if (isset($resultRaw->operating_platform) && $this->isRealResult($resultRaw->operating_platform) === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247 1
            $device->setModel($resultRaw->operating_platform);
248 1
        }
249
250 5
        if (isset($resultRaw->operating_platform_vendor_name) && $this->isRealResult($resultRaw->operating_platform_vendor_name) === true) {
251 2
            $device->setBrand($resultRaw->operating_platform_vendor_name);
252 2
        }
253 5
    }
254
255 14 View Code Duplication
    public function parse($userAgent, array $headers = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
256
    {
257 14
        $resultRaw = $this->getResult($userAgent, $headers);
258
259
        /*
260
         * No result found?
261
         */
262 6
        if ($this->hasResult($resultRaw) !== true) {
263 1
            throw new Exception\NoResultFoundException('No result found for user agent: ' . $userAgent);
264
        }
265
266
        /*
267
         * Hydrate the model
268
         */
269 5
        $result = new Model\UserAgent();
270 5
        $result->setProviderResultRaw($resultRaw);
271
272
        /*
273
         * hydrate the result
274
         */
275 5
        $this->hydrateBrowser($result->getBrowser(), $resultRaw);
276 5
        $this->hydrateRenderingEngine($result->getRenderingEngine(), $resultRaw);
277 5
        $this->hydrateOperatingSystem($result->getOperatingSystem(), $resultRaw);
278 5
        $this->hydrateDevice($result->getDevice(), $resultRaw);
279
280 5
        return $result;
281
    }
282
}
283