Completed
Push — master ( 6ae628...7ae342 )
by Elf
02:45
created

Client::remove()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 4
nop 1
crap 12
1
<?php
2
3
namespace ElfSundae\Laravel\Agent;
4
5
use Jenssegers\Agent\Agent;
6
use Illuminate\Support\Fluent;
7
use ElfSundae\Laravel\Helper\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 string app
17
 * @property string appVersion
18
 * @property string appChannel
19
 * @property string network
20
 * @property string udid
21
 */
22
class Client extends Fluent
23
{
24
    use FluentArrayAccess;
25
26
    /**
27
     * The Agent instance.
28
     *
29
     * @var \Jenssegers\Agent\Agent
30
     */
31
    protected $agent;
32
33
    /**
34
     * Return this instance.
35
     *
36
     * @return $this
37
     */
38
    public function instance()
39
    {
40
        return $this;
41
    }
42
43
    /**
44
     * Get the Agent instance.
45
     *
46
     * @return \Jenssegers\Agent\Agent
47
     */
48
    public function agent()
49
    {
50
        return $this->agent;
51
    }
52
53
    /**
54
     * Set the Agent instance.
55
     *
56
     * @param  \Jenssegers\Agent\Agent  $agent
57
     * @return $this
58
     */
59
    public function setAgent(Agent $agent)
60
    {
61
        $this->agent = $agent;
62
63
        return $this->parseAgent();
64
    }
65
66
    /**
67
     * Merge new data into the current attributes.
68
     *
69
     * @param  array  ...$data
70
     * @return $this
71
     */
72
    public function add(array ...$data)
73
    {
74
        $this->attributes = array_replace($this->attributes, ...$data);
75
76
        return $this;
77
    }
78
79
    /**
80
     * Set a given attribute value.
81
     *
82
     * @param  array|string  $key
83
     * @param  mixed   $value
84
     * @return $this
85
     */
86
    public function set($key, $value = true)
87
    {
88
        $data = is_array($key) ? $key : [$key => $value];
89
90
        return $this->add($data);
91
    }
92
93
    /**
94
     * Remove attributes.
95
     *
96
     * @param  array|string  $keys
97
     * @return $this
98
     */
99
    public function remove($keys)
100
    {
101
        $keys = is_array($keys) ? $keys : func_get_args();
102
103
        foreach ($keys as $key) {
104
            unset($this->attributes[$key]);
105
        }
106
107
        return $this;
108
    }
109
110
    /**
111
     * Check the version of the given property in the User-Agent.
112
     *
113
     * @param  string  $propertyName
114
     * @return string|float|false
115
     *
116
     * @see \Jenssegers\Agent\Agent::version()
117
     */
118
    public function version($propertyName, $type = Agent::VERSION_TYPE_STRING)
119
    {
120
        $version = $this->agent->version($propertyName, $type);
121
122
        return is_string($version) ? str_replace(['_', '+'], '.', $version) : $version;
123
    }
124
125
    /**
126
     * Check a certain value exists, case insensitived.
127
     *
128
     * @param  string  $value
129
     * @return bool
130
     */
131
    public function is($value)
132
    {
133
        return in_arrayi($value, $this->attributes) ||
134
            in_arrayi('is'.$value, array_keys($this->attributes)) ||
135
            $this->agent->is($value);
136
    }
137
138
    /**
139
     * Get or check the current app channel.
140
     *
141
     * @return string|bool
142
     */
143
    public function appChannel()
144
    {
145
        $appChannel = $this->get('appChannel');
146
147
        if (func_num_args() > 0) {
148
            if ($appChannel) {
149
                $checks = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
150
151
                return in_arrayi($appChannel, $checks);
152
            }
153
154
            return false;
155
        }
156
157
        return $appChannel;
158
    }
159
160
    /**
161
     * Set the User-Agent to be used.
162
     *
163
     * @param  string  $userAgent
164
     * @return $this
165
     */
166
    public function setUserAgent($userAgent = null)
167
    {
168
        $this->agent->setUserAgent($userAgent);
169
170
        return $this->parseAgent();
171
    }
172
173
    /**
174
     * Parse Agent information.
175
     *
176
     * @return $this
177
     */
178
    protected function parseAgent()
179
    {
180
        return $this->add(
181
            $this->parseCommonClient(),
182
            $this->parseAppClient()
183
        );
184
    }
185
186
    /**
187
     * Parse common client.
188
     *
189
     * @return array
190
     */
191
    protected function parseCommonClient()
192
    {
193
        $info = [
194
            'os' => $this->agent->platform(),
195
            'osVersion' => $this->version($this->agent->platform()),
196
            'platform' => $this->agent->device(),
197
            'locale' => head($this->agent->languages()),
198
        ];
199
200
        if ($this->agent->is('iOS')) {
201
            $info['os'] = 'iOS';
202
        }
203
204
        if ($this->agent->is('AndroidOS')) {
205
            $info['os'] = 'Android';
206
        }
207
208
        if (is_string($this->version('MicroMessenger'))) {
209
            $info['isWechat'] = true;
210
        } else {
211
            unset($info['isWechat']);
212
        }
213
214
        return array_filter($info);
215
    }
216
217
    /**
218
     * Parse app client from the User-Agent.
219
     *
220
     * @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)`
221
     *
222
     * @return array
223
     */
224
    protected function parseAppClient()
225
    {
226
        $data = $this->getAppClientAttributes(
227
            $this->getAppClientData($this->agent->getUserAgent())
228
        );
229
230
        if (empty($data)) {
231
            $this->resetAppClientAttributes();
232
        }
233
234
        return $data;
235
    }
236
237
    /**
238
     * Get app client information from the User-Agent.
239
     *
240
     * @param  string  $userAgent
241
     * @return array
242
     */
243
    protected function getAppClientData($userAgent)
244
    {
245
        if (preg_match('#client\((.+)\)#is', $userAgent, $matches)) {
246
            if ($info = json_decode(urlsafe_base64_decode($matches[1]), true)) {
247
                if (is_array($info) && ! empty($info)) {
248
                    return $info;
249
                }
250
            }
251
        }
252
253
        return [];
254
    }
255
256
    /**
257
     * Get app client attributes.
258
     *
259
     * @param  array  $info
260
     * @return array
261
     */
262
    protected function getAppClientAttributes($info)
263
    {
264
        $info = array_filter($info);
265
        $data = [];
266
267
        if (
268
            ($data['os'] = array_get($info, 'os')) &&
269
            ($data['osVersion'] = array_get($info, 'osV')) &&
270
            ($data['platform'] = array_get($info, 'pf')) &&
271
            ($data['locale'] = array_get($info, 'loc')) &&
272
            ($data['app'] = array_get($info, 'app')) &&
273
            ($data['appVersion'] = array_get($info, 'appV')) &&
274
            ($data['appChannel'] = array_get($info, 'appC')) &&
275
            ($data['network'] = array_get($info, 'net')) &&
276
            ($data['udid'] = array_get($info, 'udid'))
277
        ) {
278
            if ($data['os'] === 'iPhone OS') {
279
                $data['os'] = 'iOS';
280
            }
281
282
            $data['isAppClient'] = true;
283
284
            return array_filter($data);
285
        }
286
287
        return [];
288
    }
289
290
    /**
291
     * Reset app client attributes.
292
     */
293
    protected function resetAppClientAttributes()
294
    {
295
        unset(
296
            $this->attributes['app'],
297
            $this->attributes['appVersion'],
298
            $this->attributes['appChannel'],
299
            $this->attributes['network'],
300
            $this->attributes['udid'],
301
            $this->attributes['isAppClient']
302
        );
303
    }
304
305
    /**
306
     * Handle dynamic calls to the Agent instance.
307
     *
308
     * @param  string  $method
309
     * @param  array  $parameters
310
     * @return mixed
311
     */
312
    public function __call($method, $parameters)
313
    {
314
        return call_user_func_array([$this->agent, $method], $parameters);
315
    }
316
}
317