xero-8.x-2.x-dev/src/XeroTokenManager.php
src/XeroTokenManager.php
<?php
namespace Drupal\xero;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\user\UserDataInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Token\AccessTokenInterface;
/**
* Manages per-user or global xero access tokens.
*
* This class may be sub-classed.
*/
class XeroTokenManager implements XeroTokenManagerInterface {
use StringTranslationTrait;
/**
* The user.data service.
*
* @var \Drupal\user\UserDataInterface
*/
protected $userData;
/**
* The keyvalue storage.
*
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
*/
protected $keyValue;
/**
* Configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Initialization method.
*
* @param \Drupal\user\UserDataInterface $userData
* The user.data service.
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $keyValueFactory
* The keyvalue.database service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The config.factory service.
*/
public function __construct(UserDataInterface $userData, KeyValueFactoryInterface $keyValueFactory, ConfigFactoryInterface $configFactory) {
$this->userData = $userData;
$this->keyValue = $keyValueFactory->get('xero');
$this->configFactory = $configFactory;
}
/**
* {@inheritdoc}
*/
public function setToken(AccessTokenInterface $accessToken, ?AccountProxyInterface $account = NULL, array $organizations = []): void {
if ($account === NULL || $account->isAnonymous()) {
$this->setGlobal($accessToken, $organizations);
}
else {
$this->setUser($accessToken, $account, $organizations);
}
}
/**
* {@inheritdoc}
*/
public function getToken(AccountProxyInterface $account, $global = TRUE): AccessTokenInterface|bool {
$options = [];
$uid = $account->id();
if ($global && $account->hasPermission('access xero')) {
// Gets the global configuration if the user has access to configure it.
$options = $this->keyValue->getMultiple([
'access_token',
'refresh_token',
'expires',
]);
}
elseif (!$global && $account->hasPermission('access xero')) {
$options['access_token'] = $this->userData->get('xero', $uid, 'access_token');
$options['refresh_token'] = $this->userData->get('xero', $uid, 'refresh_token');
$options['expires'] = $this->userData->get('xero', $uid, 'expires');
}
if (!empty($options)) {
return new AccessToken($options);
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getUserOrganizations(AccountProxyInterface $account): array {
$uid = $account->id();
$orgs = $this->userData->get('xero', $uid, 'organizations');
if ($orgs) {
return json_decode($orgs, TRUE);
}
return [];
}
/**
* {@inheritdoc}
*/
public function hasUserToken(AccountProxyInterface $account): bool {
$uid = $account->id();
$access_token = $this->userData
->get('xero', $uid, 'access_token');
return $access_token !== NULL;
}
/**
* Sets the account token to global storage.
*
* @param \League\OAuth2\Client\Token\AccessTokenInterface $accessToken
* The access token.
* @param array $organizations
* The organizations available to the site.
*/
protected function setGlobal(AccessTokenInterface $accessToken, array $organizations): void {
$this->keyValue->setMultiple([
'access_token' => $accessToken->getToken(),
'refresh_token' => $accessToken->getRefreshToken(),
'expires' => $accessToken->getExpires(),
]);
// Sets the default tenant id.
$config = $this->configFactory->getEditable('xero.settings');
if (!empty($organizations)) {
// Try to match the tenant with the currently saved one or unset it as
// access has been revoked.
$tenantId = $config->get('defaults.tenant');
$tenantId = array_reduce($organizations, function ($result, $org) use ($tenantId) {
return $org['tenantId'] === $tenantId ? $org['tenantId'] : $result;
}, NULL);
$config->set('defaults.tenant', $tenantId);
$config->save();
}
}
/**
* Sets the access token for the user.
*
* @param \League\OAuth2\Client\Token\AccessTokenInterface $accessToken
* The access token.
* @param \Drupal\Core\Session\AccountProxyInterface $account
* A user account.
* @param array $organizations
* Organizations available to this user account.
*/
protected function setUser(AccessTokenInterface $accessToken, AccountProxyInterface $account, array $organizations): void {
$uid = $account->id();
$this->userData->set('xero', $uid, 'access_token', $accessToken->getToken());
$this->userData->set('xero', $uid, 'refresh_token', $accessToken->getRefreshToken());
$this->userData->set('xero', $uid, 'expires', $accessToken->getExpires());
if (!empty($organizations)) {
$this->userData->set('xero', $uid, 'organizations', json_encode($organizations));
}
}
}
