Completed
Push — master ( 7ae342...224b1d )
by Elf
02:08
created

Client::resetAppClientAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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