1 | <?php |
||||
2 | |||||
3 | namespace J4k\OAuth2\Client\Provider; |
||||
4 | |||||
5 | use League\OAuth2\Client\Provider\AbstractProvider; |
||||
6 | use League\OAuth2\Client\Provider\Exception\IdentityProviderException; |
||||
7 | use League\OAuth2\Client\Token\AccessToken; |
||||
8 | use Psr\Http\Message\ResponseInterface; |
||||
9 | |||||
10 | class Vkontakte extends AbstractProvider |
||||
11 | { |
||||
12 | protected $baseOAuthUri = 'https://oauth.vk.com'; |
||||
13 | protected $baseUri = 'https://api.vk.com/method'; |
||||
14 | protected $version = '5.7'; |
||||
15 | protected $language = null; |
||||
16 | |||||
17 | /** |
||||
18 | * @type array |
||||
19 | * @see https://vk.com/dev/permissions |
||||
20 | */ |
||||
21 | public $scopes = [ |
||||
22 | 'email', |
||||
23 | 'friends', |
||||
24 | 'offline', |
||||
25 | //'photos', |
||||
26 | //'wall', |
||||
27 | //'ads', |
||||
28 | //'audio', |
||||
29 | //'docs', |
||||
30 | //'groups', |
||||
31 | //'market', |
||||
32 | //'messages', |
||||
33 | //'nohttps', |
||||
34 | //'notes', |
||||
35 | //'notifications', |
||||
36 | //'notify', |
||||
37 | //'pages', |
||||
38 | //'stats', |
||||
39 | //'status', |
||||
40 | //'video', |
||||
41 | ]; |
||||
42 | /** |
||||
43 | * @type array |
||||
44 | * @see https://new.vk.com/dev/fields |
||||
45 | */ |
||||
46 | public $userFields = [ |
||||
47 | 'bdate', |
||||
48 | 'city', |
||||
49 | 'country', |
||||
50 | 'domain', |
||||
51 | 'first_name', |
||||
52 | 'friend_status', |
||||
53 | 'has_photo', |
||||
54 | 'home_town', |
||||
55 | 'id', |
||||
56 | 'is_friend', |
||||
57 | 'last_name', |
||||
58 | 'maiden_name', |
||||
59 | 'nickname', |
||||
60 | 'photo_max', |
||||
61 | 'photo_max_orig', |
||||
62 | 'screen_name', |
||||
63 | 'sex', |
||||
64 | //'about', |
||||
65 | //'activities', |
||||
66 | //'blacklisted', |
||||
67 | //'blacklisted_by_me', |
||||
68 | //'books', |
||||
69 | //'can_post', |
||||
70 | //'can_see_all_posts', |
||||
71 | //'can_see_audio', |
||||
72 | //'can_send_friend_request', |
||||
73 | //'can_write_private_message', |
||||
74 | //'career', |
||||
75 | //'common_count', |
||||
76 | //'connections', |
||||
77 | //'contacts', |
||||
78 | //'crop_photo', |
||||
79 | //'counters', |
||||
80 | //'deactivated', |
||||
81 | //'education', |
||||
82 | //'exports', |
||||
83 | //'followers_count', |
||||
84 | //'games', |
||||
85 | //'has_mobile', |
||||
86 | //'hidden', |
||||
87 | //'interests', |
||||
88 | //'is_favorite', |
||||
89 | //'is_hidden_from_feed', |
||||
90 | //'last_seen', |
||||
91 | //'military', |
||||
92 | //'movies', |
||||
93 | //'occupation', |
||||
94 | //'online', |
||||
95 | //'personal', |
||||
96 | //'photo_100', |
||||
97 | //'photo_200', |
||||
98 | //'photo_200_orig', |
||||
99 | //'photo_400_orig', |
||||
100 | //'photo_50', |
||||
101 | //'photo_id', |
||||
102 | //'quotes', |
||||
103 | //'relation', |
||||
104 | //'relatives', |
||||
105 | //'schools', |
||||
106 | //'site', |
||||
107 | //'status', |
||||
108 | //'timezone', |
||||
109 | //'tv', |
||||
110 | //'universities', |
||||
111 | //'verified', |
||||
112 | //'wall_comments', |
||||
113 | ]; |
||||
114 | |||||
115 | /** |
||||
116 | * @param $language |
||||
117 | * @return $this |
||||
118 | */ |
||||
119 | public function setLanguage($language) |
||||
120 | { |
||||
121 | $this->language = (string)$language; |
||||
122 | |||||
123 | return $this; |
||||
124 | } |
||||
125 | |||||
126 | /** |
||||
127 | * @return string |
||||
128 | */ |
||||
129 | public function getBaseAuthorizationUrl() |
||||
130 | { |
||||
131 | return "$this->baseOAuthUri/authorize"; |
||||
132 | } |
||||
133 | |||||
134 | /** |
||||
135 | * @return string |
||||
136 | */ |
||||
137 | public function getBaseAccessTokenUrl(array $params) |
||||
138 | { |
||||
139 | return "$this->baseOAuthUri/access_token"; |
||||
140 | } |
||||
141 | |||||
142 | /** |
||||
143 | * @param AccessToken $token |
||||
144 | * @return string |
||||
145 | */ |
||||
146 | public function getResourceOwnerDetailsUrl(AccessToken $token) |
||||
147 | { |
||||
148 | $params = [ |
||||
149 | 'fields' => $this->userFields, |
||||
150 | 'access_token' => $token->getToken(), |
||||
151 | 'v' => $this->version, |
||||
152 | 'lang' => $this->language |
||||
153 | ]; |
||||
154 | $query = $this->buildQueryString($params); |
||||
155 | $url = "$this->baseUri/users.get?$query"; |
||||
156 | |||||
157 | return $url; |
||||
158 | } |
||||
159 | |||||
160 | /** |
||||
161 | * @return array |
||||
162 | */ |
||||
163 | protected function getDefaultScopes() |
||||
164 | { |
||||
165 | return $this->scopes; |
||||
166 | } |
||||
167 | |||||
168 | /** |
||||
169 | * @param ResponseInterface $response |
||||
170 | * @param array|string $data |
||||
171 | * @throws IdentityProviderException |
||||
172 | */ |
||||
173 | protected function checkResponse(ResponseInterface $response, $data) |
||||
174 | { |
||||
175 | // Metadata info |
||||
176 | $contentTypeRaw = $response->getHeader('Content-Type'); |
||||
177 | $contentTypeArray = explode(';', reset($contentTypeRaw)); |
||||
178 | $contentType = reset($contentTypeArray); |
||||
179 | // Response info |
||||
180 | $responseCode = $response->getStatusCode(); |
||||
181 | $responseMessage = $response->getReasonPhrase(); |
||||
182 | // Data info |
||||
183 | $error = !empty($data['error']) ? $data['error'] : null; |
||||
184 | $errorCode = !empty($error['error_code']) ? $error['error_code'] : $responseCode; |
||||
185 | $errorDescription = !empty($data['error_description']) ? $data['error_description'] : null; |
||||
186 | $errorMessage = !empty($error['error_msg']) ? $error['error_msg'] : $errorDescription; |
||||
187 | $message = $errorMessage ?: $responseMessage; |
||||
188 | |||||
189 | // Request/meta validation |
||||
190 | if (399 < $responseCode) { |
||||
191 | throw new IdentityProviderException($message, $responseCode, $data); |
||||
192 | } |
||||
193 | |||||
194 | // Content validation |
||||
195 | if ('application/json' != $contentType) { |
||||
196 | throw new IdentityProviderException($message, $responseCode, $data); |
||||
197 | } |
||||
198 | if ($error) { |
||||
199 | throw new IdentityProviderException($errorMessage, $errorCode, $data); |
||||
200 | } |
||||
201 | } |
||||
202 | |||||
203 | /** |
||||
204 | * @param array $response |
||||
205 | * @param AccessToken $token |
||||
206 | * @return User|\League\OAuth2\Client\Provider\ResourceOwnerInterface |
||||
207 | */ |
||||
208 | protected function createResourceOwner(array $response, AccessToken $token) |
||||
209 | { |
||||
210 | $response = reset($response['response']); |
||||
211 | $additional = $token->getValues(); |
||||
212 | if (!empty($additional['email'])) { |
||||
213 | $response['email'] = $additional['email']; |
||||
214 | } |
||||
215 | if (!empty($response['uid']) && 4 === floor($this->version)) { |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
216 | $response['id'] = $response['uid']; |
||||
217 | } |
||||
218 | if (!empty($additional['user_id'])) { |
||||
219 | $response['id'] = $additional['user_id']; |
||||
220 | } |
||||
221 | // @TODO Investigate and fix this code smell |
||||
222 | |||||
223 | return new User($response, $response['id']); |
||||
0 ignored issues
–
show
The call to
J4k\OAuth2\Client\Provider\User::__construct() has too many arguments starting with $response['id'] .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
224 | } |
||||
225 | |||||
226 | /** |
||||
227 | * @see https://vk.com/dev/users.get |
||||
228 | * |
||||
229 | * @param integer[] $ids |
||||
230 | * @param AccessToken|null $token Current user if empty |
||||
231 | * @param array $params |
||||
232 | * |
||||
233 | * @return User[] |
||||
234 | */ |
||||
235 | public function usersGet(array $ids = [], AccessToken $token = null, array $params = []) |
||||
236 | { |
||||
237 | if (empty($ids) && !$token) { |
||||
238 | throw new \InvalidArgumentException('Some of parameters usersIds OR access_token are required'); |
||||
239 | } |
||||
240 | |||||
241 | $default = [ |
||||
242 | 'user_ids' => implode(',', $ids), |
||||
243 | 'fields' => $this->userFields, |
||||
244 | 'access_token' => $token ? $token->getToken() : null, |
||||
245 | 'v' => $this->version, |
||||
246 | 'lang' => $this->language |
||||
247 | ]; |
||||
248 | $params = array_merge($default, $params); |
||||
249 | $query = $this->buildQueryString($params); |
||||
250 | $url = "$this->baseUri/users.get?$query"; |
||||
251 | |||||
252 | $response = $this->getResponse($this->createRequest(static::METHOD_GET, $url, $token, []))['response']; |
||||
253 | $users = !empty($response['items']) ? $response['items'] : $response; |
||||
254 | $array2user = function ($userData) { |
||||
255 | return new User($userData); |
||||
256 | }; |
||||
257 | |||||
258 | return array_map($array2user, $users); |
||||
259 | } |
||||
260 | |||||
261 | /** |
||||
262 | * @see https://vk.com/dev/friends.get |
||||
263 | * |
||||
264 | * @param integer $userId |
||||
265 | * @param AccessToken|null $token |
||||
266 | * @param array $params |
||||
267 | * |
||||
268 | * @return User[] |
||||
269 | */ |
||||
270 | public function friendsGet($userId, AccessToken $token = null, array $params = []) |
||||
271 | { |
||||
272 | $default = [ |
||||
273 | 'user_id' => $userId, |
||||
274 | 'fields' => $this->userFields, |
||||
275 | 'access_token' => $token ? $token->getToken() : null, |
||||
276 | 'v' => $this->version, |
||||
277 | 'lang' => $this->language |
||||
278 | ]; |
||||
279 | $params = array_merge($default, $params); |
||||
280 | $query = $this->buildQueryString($params); |
||||
281 | $url = "$this->baseUri/friends.get?$query"; |
||||
282 | |||||
283 | $response = $this->getResponse($this->createRequest(static::METHOD_GET, $url, $token, []))['response']; |
||||
284 | $friends = !empty($response['items']) ? $response['items'] : $response; |
||||
285 | $array2friend = function ($friendData) { |
||||
286 | if (is_numeric($friendData)) { |
||||
287 | $friendData = ['id' => $friendData]; |
||||
288 | } |
||||
289 | |||||
290 | return new User($friendData); |
||||
291 | }; |
||||
292 | |||||
293 | return array_map($array2friend, $friends); |
||||
294 | } |
||||
295 | } |
||||
296 |