Completed
Push — master ( ffbaba...99b42b )
by Elf
03:27
created

Client::agent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
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
     * Get the Agent instance.
35
     *
36
     * @return \Jenssegers\Agent\Agent
37
     */
38
    public function agent()
39
    {
40
        return $this->agent;
41
    }
42
43
    /**
44
     * Set the Agent instance.
45
     *
46
     * @param  \Jenssegers\Agent\Agent  $agent
47
     * @return $this
48
     */
49
    public function setAgent(Agent $agent)
50
    {
51
        $this->agent = $agent;
52
53
        return $this->parseAgent();
54
    }
55
56
    /**
57
     * Merge new data into the current attributes.
58
     *
59
     * @param  array  ...$data
60
     * @return $this
61
     */
62
    public function add(array ...$data)
63
    {
64
        $this->attributes = array_replace($this->attributes, ...$data);
65
66
        return $this;
67
    }
68
69
    /**
70
     * Check the version of the given property in the User-Agent.
71
     *
72
     * @param  string  $propertyName
73
     * @return string|float|false
74
     *
75
     * @see \Jenssegers\Agent\Agent::version()
76
     */
77
    public function version($propertyName, $type = Agent::VERSION_TYPE_STRING)
78
    {
79
        $version = $this->agent->version($propertyName, $type);
80
81
        return is_string($version) ? str_replace(['_', '+'], '.', $version) : $version;
82
    }
83
84
    /**
85
     * Check a certain value exists, case insensitived.
86
     *
87
     * @param  string  $value
88
     * @return bool
89
     */
90
    public function is($value)
91
    {
92
        return in_arrayi($value, $this->attributes) ||
93
            in_arrayi('is'.$value, array_keys($this->attributes)) ||
94
            $this->agent->is($value);
95
    }
96
97
    /**
98
     * Get or check the current app channel.
99
     *
100
     * @return string|bool
101
     */
102
    public function appChannel()
103
    {
104
        $appChannel = $this->get('appChannel');
105
106
        if (func_num_args() > 0) {
107
            $checks = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
108
109
            return $appChannel ? in_arrayi($appChannel, $checks) : false;
110
        }
111
112
        return $appChannel;
113
    }
114
115
    /**
116
     * Set the User-Agent to be used.
117
     *
118
     * @param  string  $userAgent
119
     * @return $this
120
     */
121
    public function setUserAgent($userAgent = null)
122
    {
123
        $this->agent->setUserAgent($userAgent);
124
125
        return $this->parseAgent();
126
    }
127
128
    /**
129
     * Parse Agent information.
130
     *
131
     * @return $this
132
     */
133
    protected function parseAgent()
134
    {
135
        return $this->add(
136
            $this->parseCommonClient(),
137
            $this->parseAppClient()
138
        );
139
    }
140
141
    /**
142
     * Parse common client.
143
     *
144
     * @return array
145
     */
146
    protected function parseCommonClient()
147
    {
148
        $info = [
149
            'os' => $this->agent->platform(),
150
            'osVersion' => $this->version($this->agent->platform()),
151
            'platform' => $this->agent->device(),
152
            'locale' => head($this->agent->languages()),
153
        ];
154
155
        if ($this->agent->is('iOS')) {
156
            $info['os'] = 'iOS';
157
        }
158
159
        if ($this->agent->is('AndroidOS')) {
160
            $info['os'] = 'Android';
161
        }
162
163
        if (is_string($this->version('MicroMessenger'))) {
164
            $info['isWechat'] = true;
165
        } else {
166
            unset($info['isWechat']);
167
        }
168
169
        return array_filter($info);
170
    }
171
172
    /**
173
     * Parse app client from the User-Agent.
174
     *
175
     * @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)`
176
     *
177
     * @return array
178
     */
179
    protected function parseAppClient()
180
    {
181
        $data = $this->getAppClientAttributes(
182
            $this->getAppClientData($this->agent->getUserAgent())
183
        );
184
185
        if (! $data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
186
            $this->resetAppClientAttributes();
187
        }
188
189
        return $data;
190
    }
191
192
    /**
193
     * Get app client information from the User-Agent.
194
     *
195
     * @param  string  $userAgent
196
     * @return array
197
     */
198
    protected function getAppClientData($userAgent)
199
    {
200
        if (preg_match('#client\((.+)\)#is', $userAgent, $matches)) {
201
            if ($info = json_decode(urlsafe_base64_decode($matches[1]), true)) {
202
                if (is_array($info) && ! empty($info)) {
203
                    return $info;
204
                }
205
            }
206
        }
207
208
        return [];
209
    }
210
211
    /**
212
     * Get app client attributes.
213
     *
214
     * @param  array  $info
215
     * @return array
216
     */
217
    protected function getAppClientAttributes($info)
218
    {
219
        $info = array_filter($info);
220
        $data = [];
221
222
        if (
223
            ($data['os'] = array_get($info, 'os')) &&
224
            ($data['osVersion'] = array_get($info, 'osV')) &&
225
            ($data['platform'] = array_get($info, 'pf')) &&
226
            ($data['locale'] = array_get($info, 'loc')) &&
227
            ($data['app'] = array_get($info, 'app')) &&
228
            ($data['appVersion'] = array_get($info, 'appV')) &&
229
            ($data['appChannel'] = array_get($info, 'appC')) &&
230
            ($data['network'] = array_get($info, 'net')) &&
231
            ($data['udid'] = array_get($info, 'udid'))
232
        ) {
233
            if ($data['os'] === 'iPhone OS') {
234
                $data['os'] = 'iOS';
235
            }
236
237
            $data['isAppClient'] = true;
238
239
            return array_filter($data);
240
        }
241
242
        return [];
243
    }
244
245
    /**
246
     * Reset app client attributes.
247
     */
248
    protected function resetAppClientAttributes()
249
    {
250
        unset(
251
            $this->attributes['app'],
252
            $this->attributes['appVersion'],
253
            $this->attributes['appChannel'],
254
            $this->attributes['network'],
255
            $this->attributes['udid'],
256
            $this->attributes['isAppClient']
257
        );
258
    }
259
260
    /**
261
     * Handle dynamic calls to the Agent instance.
262
     *
263
     * @param  string  $method
264
     * @param  array  $parameters
265
     * @return mixed
266
     */
267
    public function __call($method, $parameters)
268
    {
269
        return call_user_func_array([$this->agent, $method], $parameters);
270
    }
271
}
272