Completed
Push — master ( 279d4e...5d09e0 )
by Elf
02:49
created

Client::getApiClientAttributes()   C

Complexity

Conditions 13
Paths 7

Size

Total Lines 43
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 0
Metric Value
cc 13
eloc 29
nc 7
nop 1
dl 0
loc 43
ccs 0
cts 35
cp 0
crap 182
rs 5.1234
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace ElfSundae\Laravel\Support;
4
5
use Jenssegers\Agent\Agent;
6
use Illuminate\Support\Fluent;
7
use ElfSundae\Laravel\Support\Traits\FluentArrayAccess;
8
9
/**
10
 * The app client.
11
 *
12
 * @property string os
13
 * @property string osVersion
14
 * @property string platform
15
 * @property string locale
16
 * @property bool isIOS
17
 * @property bool isAndroid
18
 * @property bool isWechat
19
 * @property bool isApiClient
20
 * @property string network
21
 * @property string app
22
 * @property string appVersion
23
 * @property string appChannel
24
 * @property string tdid
25
 * @property bool isAppStoreChannel
26
 * @property bool isDebugChannel
27
 * @property bool isAdHocChannel
28
 * @property bool isInHouseChannel
29
 * @property bool isAppStoreReviewing
30
 */
31
class Client extends Fluent
32
{
33
    use FluentArrayAccess;
34
35
    /**
36
     * The Agent instance.
37
     *
38
     * @var \Jenssegers\Agent\Agent
39
     */
40
    protected $agent;
41
42
    /**
43
     * Create a new Client instance.
44
     *
45
     * @param  array|object  $attributes
46
     */
47
    public function __construct($attributes = [])
48
    {
49
        parent::__construct($attributes);
50
51
        $this->setAgent(app('agent'));
52
    }
53
54
    /**
55
     * Merge new data into the current attributes.
56
     *
57
     * @param  array  ...$data
58
     * @return $this
59
     */
60
    public function add(array ...$data)
61
    {
62
        $this->attributes = array_replace($this->attributes, ...$data);
63
64
        return $this;
65
    }
66
67
    /**
68
     * Check the version of the given property in the User-Agent.
69
     *
70
     * @param  string  $propertyName
71
     * @return string|float|false
72
     *
73
     * @see \Jenssegers\Agent\Agent::version()
74
     */
75
    public function version($propertyName, $type = Agent::VERSION_TYPE_STRING)
76
    {
77
        $version = $this->agent->version($propertyName, $type);
78
79
        return is_string($version) ? str_replace(['_', '+'], '.', $version) : $version;
80
    }
81
82
    /**
83
     * Get the Agent instance.
84
     *
85
     * @return \Jenssegers\Agent\Agent
86
     */
87
    public function agent()
88
    {
89
        return $this->agent;
90
    }
91
92
    /**
93
     * Set the Agent instance.
94
     *
95
     * @param  \Jenssegers\Agent\Agent  $agent
96
     * @return $this
97
     */
98
    public function setAgent(Agent $agent)
99
    {
100
        $this->agent = $agent;
101
102
        return $this->parseAgent();
103
    }
104
105
    /**
106
     * Set the User-Agent to be used.
107
     *
108
     * @param  string  $userAgent
109
     * @return $this
110
     */
111
    public function setUserAgent($userAgent = null)
112
    {
113
        $this->agent->setUserAgent($userAgent);
114
115
        return $this->parseAgent();
116
    }
117
118
    /**
119
     * Parse Agent information.
120
     *
121
     * @return $this
122
     */
123
    public function parseAgent()
124
    {
125
        $this->add(
126
            $this->parseCommonClient(),
127
            $this->parseApiClient()
128
        );
129
    }
130
131
    /**
132
     * Parse common client.
133
     *
134
     * @return array
135
     */
136
    protected function parseCommonClient()
137
    {
138
        $info = [
139
            'os' => $this->agent->platform(),
140
            'osVersion' => $this->version($this->agent->platform()),
141
            'platform' => $this->agent->device(),
142
            'locale' => head($this->agent->languages()),
143
        ];
144
145
        if ((bool) $this->agent->is('iOS')) {
146
            $info['isIOS'] = true;
147
        }
148
149
        if ((bool) $this->agent->is('AndroidOS')) {
150
            $info['isAndroid'] = true;
151
            $info['os'] = 'Android';
152
        }
153
154
        if (is_string($this->version('MicroMessenger'))) {
155
            $info['isWechat'] = true;
156
        }
157
158
        return array_filter($info);
159
    }
160
161
    /**
162
     * Parse API client from the User-Agent.
163
     *
164
     * @example `Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H143 _ua(eyJuZXQiOiJXaUZpIiwib3MiOiJpT1MiLCJhcHBWIjoiMC4xLjIiLCJvc1YiOiI4LjQiLCJhcHAiOiJndXBpYW8iLCJhcHBDIjoiRGVidWciLCJ0ZGlkIjoiaDNiYjFmNTBhYzBhMzdkYmE4ODhlMTgyNjU3OWJkZmZmIiwiYWNpZCI6IjIxZDNmYmQzNDNmMjViYmI0MzU2ZGEyMmJmZjUxZDczZjg0YWQwNmQiLCJsb2MiOiJ6aF9DTiIsInBmIjoiaVBob25lNywxIn0)`
165
     *
166
     * @return array
167
     */
168
    protected function parseApiClient()
169
    {
170
        return $this->getApiClientAttributes(
171
            $this->getApiClientInfo($this->agent->getUserAgent())
172
        );
173
    }
174
175
    /**
176
     * Get API client information from the User-Agent.
177
     *
178
     * @param  string  $userAgent
179
     * @return array
180
     */
181
    protected function getApiClientInfo($userAgent)
182
    {
183
        if (preg_match('#ua\((.+)\)#is', $userAgent, $matches)) {
184
            if ($info = json_decode(urlsafe_base64_decode($matches[1]), true)) {
185
                if (is_array($info) && count($info) > 0) {
186
                    return $info;
187
                }
188
            }
189
        }
190
191
        return [];
192
    }
193
194
    /**
195
     * Get API client attributes.
196
     *
197
     * @param  array  $info
198
     * @return array
199
     */
200
    protected function getApiClientAttributes($info)
201
    {
202
        $info = array_filter($info);
203
        $data = [];
204
205
        if (
206
            ($data['os'] = array_get($info, 'os')) &&
207
            ($data['osVersion'] = array_get($info, 'osV')) &&
208
            ($data['platform'] = array_get($info, 'pf')) &&
209
            ($data['locale'] = array_get($info, 'loc')) &&
210
            ($data['network'] = array_get($info, 'net')) &&
211
            ($data['app'] = array_get($info, 'app')) &&
212
            ($data['appVersion'] = array_get($info, 'appV')) &&
213
            ($data['appChannel'] = array_get($info, 'appC')) &&
214
            ($data['tdid'] = array_get($info, 'tdid'))
215
        ) {
216
            if ($data['os'] === 'iPhone OS') {
217
                $data['os'] = 'iOS';
218
            }
219
220
            $data['isIOS'] = $data['os'] === 'iOS';
221
            $data['isAndroid'] = $data['os'] === 'Android';
222
223
            $data['isAppStoreChannel'] = $data['appChannel'] === 'App Store';
224
            $data['isDebugChannel'] = $data['appChannel'] === 'Debug';
225
            $data['isAdHocChannel'] = $data['appChannel'] === 'Ad Hoc';
226
            $data['isInHouseChannel'] = $data['appChannel'] === 'In House';
227
228
            $data['isAppStoreReviewing'] = (
229
                $data['isIOS'] &&
230
                $data['isAppStoreChannel'] &&
231
                $data['appVersion'] === config('var.ios.app_store_reviewing_version')
232
            );
233
234
            $data['isApiClient'] = true;
235
236
            return array_filter($data);
237
        }
238
239
        $this->resetApiClientAttributes();
240
241
        return [];
242
    }
243
244
    /**
245
     * Reset API client attributes.
246
     */
247
    protected function resetApiClientAttributes()
248
    {
249
        unset(
250
            $this->attributes['network'],
251
            $this->attributes['app'],
252
            $this->attributes['appVersion'],
253
            $this->attributes['appChannel'],
254
            $this->attributes['tdid'],
255
            $this->attributes['isAppStoreChannel'],
256
            $this->attributes['isDebugChannel'],
257
            $this->attributes['isAdHocChannel'],
258
            $this->attributes['isInHouseChannel'],
259
            $this->attributes['isAppStoreReviewing']
260
        );
261
    }
262
263
    /**
264
     * Handle dynamic calls to the Agent instance.
265
     *
266
     * @param  string  $method
267
     * @param  array  $parameters
268
     * @return mixed
269
     */
270
    public function __call($method, $parameters)
271
    {
272
        return call_user_func_array([$this->agent, $method], $parameters);
273
    }
274
}
275