Completed
Push — master ( d6d8a1...fab734 )
by Elf
04:41
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
cc 1
eloc 8
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 11
ccs 0
cts 11
cp 0
crap 2
rs 9.4285
1
<?php
2
3
namespace ElfSundae\Laravel\Support\Services\Agent;
4
5
use Illuminate\Support\Arr;
6
use Jenssegers\Agent\Agent;
7
use Illuminate\Support\Fluent;
8
use ElfSundae\Laravel\Support\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
 * @property bool isAppStoreReviewing
23
 */
24
class Client extends Fluent
25
{
26
    use FluentArrayAccess;
27
28
    /**
29
     * The Agent instance.
30
     *
31
     * @var \Jenssegers\Agent\Agent
32
     */
33
    protected $agent;
34
35
    /**
36
     * Get the Agent instance.
37
     *
38
     * @return \Jenssegers\Agent\Agent
39
     */
40
    public function agent()
41
    {
42
        return $this->agent;
43
    }
44
45
    /**
46
     * Set the Agent instance.
47
     *
48
     * @param  \Jenssegers\Agent\Agent  $agent
49
     * @return $this
50
     */
51
    public function setAgent(Agent $agent)
52
    {
53
        $this->agent = $agent;
54
55
        return $this->parseAgent();
56
    }
57
58
    /**
59
     * Merge new data into the current attributes.
60
     *
61
     * @param  array  ...$data
62
     * @return $this
63
     */
64
    public function add(array ...$data)
65
    {
66
        $this->attributes = array_replace($this->attributes, ...$data);
67
68
        return $this;
69
    }
70
71
    /**
72
     * Check the version of the given property in the User-Agent.
73
     *
74
     * @param  string  $propertyName
75
     * @return string|float|false
76
     *
77
     * @see \Jenssegers\Agent\Agent::version()
78
     */
79
    public function version($propertyName, $type = Agent::VERSION_TYPE_STRING)
80
    {
81
        $version = $this->agent->version($propertyName, $type);
82
83
        return is_string($version) ? str_replace(['_', '+'], '.', $version) : $version;
84
    }
85
86
    /**
87
     * Check a certain value exists, case insensitived.
88
     *
89
     * @param  string  $value
90
     * @return bool
91
     */
92
    public function is($value)
93
    {
94
        return in_arrayi($value, $this->attributes) ||
95
            in_arrayi('is'.$value, array_keys($this->attributes)) ||
96
            $this->agent->is($value);
97
    }
98
99
    /**
100
     * Get or check the current app channel.
101
     *
102
     * @return string|bool
103
     */
104
    public function appChannel()
105
    {
106
        if (func_num_args() > 0) {
107
            $checkChannels = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();
108
109
            return in_arrayi($this->attributes['appChannel'], $checkChannels);
110
        }
111
112
        return $this->attributes['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
        }
166
167
        return array_filter($info);
168
    }
169
170
    /**
171
     * Parse app client from the User-Agent.
172
     *
173
     * @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)`
174
     *
175
     * @return array
176
     */
177
    protected function parseAppClient()
178
    {
179
        $data = $this->getAppClientAttributes(
180
            $this->getAppClientData($this->agent->getUserAgent())
181
        );
182
183
        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...
184
            $this->resetAppClientAttributes();
185
        }
186
187
        return $data;
188
    }
189
190
    /**
191
     * Get app client information from the User-Agent.
192
     *
193
     * @param  string  $userAgent
194
     * @return array
195
     */
196
    protected function getAppClientData($userAgent)
197
    {
198
        if (preg_match('#client\((.+)\)#is', $userAgent, $matches)) {
199
            if ($info = json_decode(urlsafe_base64_decode($matches[1]), true)) {
200
                if (is_array($info) && ! empty($info)) {
201
                    return $info;
202
                }
203
            }
204
        }
205
206
        return [];
207
    }
208
209
    /**
210
     * Get app client attributes.
211
     *
212
     * @param  array  $info
213
     * @return array
214
     */
215
    protected function getAppClientAttributes($info)
216
    {
217
        $info = array_filter($info);
218
        $data = [];
219
220
        if (
221
            ($data['os'] = array_get($info, 'os')) &&
222
            ($data['osVersion'] = array_get($info, 'osV')) &&
223
            ($data['platform'] = array_get($info, 'pf')) &&
224
            ($data['locale'] = array_get($info, 'loc')) &&
225
            ($data['app'] = array_get($info, 'app')) &&
226
            ($data['appVersion'] = array_get($info, 'appV')) &&
227
            ($data['appChannel'] = array_get($info, 'appC')) &&
228
            ($data['network'] = array_get($info, 'net')) &&
229
            ($data['udid'] = array_get($info, 'udid'))
230
        ) {
231
            if ($data['os'] === 'iPhone OS') {
232
                $data['os'] = 'iOS';
233
            }
234
235
            $data['isAppClient'] = true;
236
237
            return array_filter($data);
238
        }
239
240
        return [];
241
    }
242
243
    /**
244
     * Reset app client attributes.
245
     */
246
    protected function resetAppClientAttributes()
247
    {
248
        unset(
249
            $this->attributes['app'],
250
            $this->attributes['appVersion'],
251
            $this->attributes['appChannel'],
252
            $this->attributes['network'],
253
            $this->attributes['udid'],
254
            $this->attributes['isAppClient']
255
        );
256
    }
257
258
    /**
259
     * Handle dynamic calls to the Agent instance.
260
     *
261
     * @param  string  $method
262
     * @param  array  $parameters
263
     * @return mixed
264
     */
265
    public function __call($method, $parameters)
266
    {
267
        return call_user_func_array([$this->agent, $method], $parameters);
268
    }
269
}
270