Files
oauth2-vkontakte/src/VkProvider.php
2025-01-11 01:36:15 +03:00

274 lines
7.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Sept\OAuth2\Client\Provider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use Psr\Http\Message\ResponseInterface;
class VkProvider extends AbstractProvider
{
protected string $baseOAuthUri = 'https://oauth.vk.com';
protected string $baseUri = 'https://api.vk.com/method';
protected float $version = 5.199;
protected ?string $language = null;
/**
* @see https://vk.com/dev/permissions
*/
public array $scopes = [
'email',
// 'friends',
// 'offline',
// 'photos',
// 'wall',
// 'ads',
// 'audio',
// 'docs',
// 'groups',
// 'market',
// 'messages',
// 'nohttps',
// 'notes',
// 'notifications',
// 'notify',
// 'pages',
// 'stats',
// 'status',
// 'video',
];
/**
* @see https://new.vk.com/dev/fields
*/
public array $userFields = [
'bdate',
'city',
'country',
'domain',
'first_name',
'friend_status',
'has_photo',
'home_town',
'id',
'is_friend',
'last_name',
'maiden_name',
'nickname',
'photo_max',
'photo_max_orig',
'screen_name',
'sex',
'deactivated',
'is_closed',
// 'about',
// 'activities',
// 'blacklisted',
// 'blacklisted_by_me',
// 'books',
// 'can_post',
// 'can_see_all_posts',
// 'can_see_audio',
// 'can_send_friend_request',
// 'can_write_private_message',
// 'career',
// 'common_count',
// 'connections',
// 'contacts',
// 'crop_photo',
// 'counters',
// 'deactivated',
// 'education',
// 'exports',
// 'followers_count',
// 'games',
// 'has_mobile',
// 'hidden',
// 'interests',
// 'is_favorite',
// 'is_hidden_from_feed',
// 'last_seen',
// 'military',
// 'movies',
// 'occupation',
// 'online',
// 'personal',
// 'photo_100',
// 'photo_200',
// 'photo_200_orig',
// 'photo_400_orig',
// 'photo_50',
// 'photo_id',
// 'quotes',
// 'relation',
// 'relatives',
// 'schools',
// 'site',
// 'status',
// 'timezone',
// 'tv',
// 'universities',
// 'verified',
// 'wall_comments',
];
public function setLanguage(string $language): self
{
$this->language = $language;
return $this;
}
public function getBaseAuthorizationUrl(): string
{
return "$this->baseOAuthUri/authorize";
}
public function getBaseAccessTokenUrl(array $params): string
{
return "$this->baseOAuthUri/access_token";
}
public function getResourceOwnerDetailsUrl(AccessToken $token): string
{
$params = [
'fields' => $this->userFields,
'access_token' => $token->getToken(),
'v' => $this->version,
'lang' => $this->language,
];
$query = $this->buildQueryString($params);
$url = "$this->baseUri/users.get?$query";
return $url;
}
protected function getDefaultScopes(): array
{
return $this->scopes;
}
protected function checkResponse(ResponseInterface $response, $data): void
{
// Metadata info
$contentTypeRaw = $response->getHeader('Content-Type');
$contentTypeArray = explode(';', reset($contentTypeRaw));
$contentType = reset($contentTypeArray);
// Response info
$responseCode = $response->getStatusCode();
$responseMessage = $response->getReasonPhrase();
// Data info
$error = !empty($data['error']) ? $data['error'] : null;
$errorCode = !empty($error['error_code']) ? $error['error_code'] : $responseCode;
$errorDescription = !empty($data['error_description']) ? $data['error_description'] : null;
$errorMessage = !empty($error['error_msg']) ? $error['error_msg'] : $errorDescription;
$message = (bool) $errorMessage ? $errorMessage : $responseMessage;
// Request/meta validation
if (399 < $responseCode) {
throw new IdentityProviderException($message, $responseCode, $data);
}
// Content validation
if ('application/json' !== $contentType) {
throw new IdentityProviderException($message, $responseCode, $data);
}
if ($error) {
throw new IdentityProviderException($errorMessage, $errorCode, $data);
}
}
protected function createResourceOwner(array $response, AccessToken $token): VkUser
{
$response = reset($response['response']);
$additional = $token->getValues();
if (!empty($additional['email'])) {
$response['email'] = $additional['email'];
}
if (!empty($response['uid']) && 4 === (int) floor($this->version)) {
$response['id'] = $response['uid'];
}
if (!empty($additional['user_id'])) {
$response['id'] = $additional['user_id'];
}
return new VkUser($response);
}
/**
* Возвращает массив объектов пользователей.
*
* @see https://vk.com/dev/users.get
*/
public function usersGet(array $ids = [], ?AccessToken $token = null, array $params = []): array
{
if (empty($ids) && null === $token) {
throw new \InvalidArgumentException('Some of parameters usersIds OR access_token are required');
}
$default = [
'user_ids' => implode(',', $ids),
'fields' => $this->userFields,
'access_token' => null !== $token ? $token->getToken() : null,
'v' => $this->version,
'lang' => $this->language,
];
$params = array_merge($default, $params);
$query = $this->buildQueryString($params);
$url = "$this->baseUri/users.get?$query";
$response = $this->getResponse($this->createRequest(static::METHOD_GET, $url, $token, []))['response'];
$users = !empty($response['items']) ? $response['items'] : $response;
$array2user = function (mixed $userData) {
return new VkUser($userData);
};
return array_map($array2user, $users);
}
/**
* Возвращает список идентификаторов (id) друзей пользователя,
* если параметр fields не использовался. При использовании
* параметра fields возвращает список объектов пользователей,
* но не более 5000.
*
* @see https://vk.com/dev/friends.get
*/
public function friendsGet(int $userId, ?AccessToken $token = null, array $params = []): array
{
$default = [
'user_id' => $userId,
'fields' => $this->userFields,
'access_token' => null !== $token ? $token->getToken() : null,
'v' => $this->version,
'lang' => $this->language,
];
$params = array_merge($default, $params);
$query = $this->buildQueryString($params);
$url = "$this->baseUri/friends.get?$query";
$response = $this->getResponse($this->createRequest(static::METHOD_GET, $url, $token, []))['response'];
$friends = !empty($response['items']) ? $response['items'] : $response;
$array2friend = function (mixed $friendData) {
if (is_numeric($friendData)) {
$friendData = ['id' => $friendData];
}
return new VkUser($friendData);
};
return array_map($array2friend, $friends);
}
}