mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-27 23:20:28 +01:00
324 lines
9.1 KiB
PHP
324 lines
9.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Xentral\Modules\GoogleApi\Service;
|
|
|
|
use Exception;
|
|
use Xentral\Components\Database\Database;
|
|
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
|
use Xentral\Modules\GoogleApi\Data\GoogleAccessTokenData;
|
|
use Xentral\Modules\GoogleApi\Data\GoogleAccountPropertyValue;
|
|
use Xentral\Modules\GoogleApi\Data\GoogleAccountPropertyCollection;
|
|
use Xentral\Modules\GoogleApi\Data\GoogleAccountData;
|
|
use Xentral\Modules\GoogleApi\Exception\GoogleAccountGatewayException;
|
|
use Xentral\Modules\GoogleApi\Exception\GoogleAccountNotFoundException;
|
|
use Xentral\Modules\GoogleApi\Exception\NoAccessTokenException;
|
|
use Xentral\Modules\GoogleApi\GoogleScope;
|
|
|
|
final class GoogleAccountGateway
|
|
{
|
|
/** @var Database $db */
|
|
private $db;
|
|
|
|
/**
|
|
* @param Database $database
|
|
*/
|
|
public function __construct(Database $database)
|
|
{
|
|
$this->db = $database;
|
|
}
|
|
|
|
/**
|
|
* @param int $id
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function existsAccount(int $id): bool
|
|
{
|
|
$sql = 'SELECT ga.id FROM `google_account` AS `ga` WHERE ga.id = :id';
|
|
$resultId = $this->db->fetchValue($sql, ['id' => $id]);
|
|
|
|
return $resultId === $id;
|
|
}
|
|
|
|
/**
|
|
* @param int $id
|
|
*
|
|
* @throws GoogleAccountNotFoundException
|
|
*
|
|
* @return GoogleAccountData
|
|
*/
|
|
public function getAccount(int $id): GoogleAccountData
|
|
{
|
|
$query = $this->buildAccountQuery()
|
|
->where('ga.id = :id');
|
|
$values = ['id' => $id];
|
|
$account = $this->queryAccount($query, $values);
|
|
if ($account === null) {
|
|
throw new GoogleAccountNotFoundException('Google Account not Available.');
|
|
}
|
|
|
|
return $account;
|
|
}
|
|
|
|
/**
|
|
* @param int $userId
|
|
*
|
|
* @throws GoogleAccountNotFoundException
|
|
*
|
|
* @return GoogleAccountData
|
|
*/
|
|
public function getAccountByUser(int $userId): GoogleAccountData
|
|
{
|
|
$query = $this->buildAccountQuery()
|
|
->where('ga.user_id = :user_id');
|
|
$values = ['user_id' => $userId];
|
|
$account = $this->queryAccount($query, $values);
|
|
if ($account === null) {
|
|
throw new GoogleAccountNotFoundException(
|
|
sprintf('No Google account found for user "%s"', $userId)
|
|
);
|
|
}
|
|
|
|
return $account;
|
|
}
|
|
|
|
/**
|
|
* @param string $email
|
|
*
|
|
* @throws GoogleAccountNotFoundException
|
|
*
|
|
* @return GoogleAccountData
|
|
*/
|
|
public function getAccountByGmailAddress(string $email): GoogleAccountData
|
|
{
|
|
try {
|
|
$query = $this->buildAccountQuery()
|
|
->join('', 'google_account_property AS gp', 'ga.id = gp.google_account_id')
|
|
->where("gp.varname = :varname AND gp.value = :email");
|
|
$values = ['varname' => 'gmail_address', 'email' => $email];
|
|
$account = $this->queryAccount($query, $values);
|
|
} catch (Exception $e) {
|
|
throw new GoogleAccountNotFoundException($e->getMessage(), $e->getCode(), $e);
|
|
}
|
|
if ($account === null) {
|
|
throw new GoogleAccountNotFoundException(
|
|
sprintf('No Google Account found for email address "%s"', $email)
|
|
);
|
|
}
|
|
|
|
return $account;
|
|
}
|
|
|
|
|
|
/**
|
|
* Gets all accounts that have a certain scope
|
|
*
|
|
* @param string $scope
|
|
*
|
|
* @return GoogleAccountData[]|array
|
|
*/
|
|
public function getAccountsByScope(string $scope): array
|
|
{
|
|
try {
|
|
$query = $this->buildAccountQuery()
|
|
->join('', 'google_account_scope AS gs', 'ga.id = gs.google_account_id')
|
|
->where('gs.scope = :scope');
|
|
$values = ['scope' => $scope];
|
|
$rows = $this->db->fetchAll($query->getStatement(), $values);
|
|
$accounts = [];
|
|
foreach ($rows as $row) {
|
|
$accounts[] = GoogleAccountData::fromDbState($row);
|
|
}
|
|
|
|
return $accounts;
|
|
} catch (Exception $e) {
|
|
throw new GoogleAccountGatewayException($e->getMessage(), $e->getCode(), $e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $addressId
|
|
*
|
|
* @throws GoogleAccountGatewayException
|
|
*
|
|
* @return GoogleAccountData|null
|
|
*/
|
|
public function tryGetAccountByAddress(int $addressId): ?GoogleAccountData
|
|
{
|
|
try {
|
|
$query = $this->buildAccountQuery()
|
|
->join('', 'user AS u', 'ga.user_id = u.id')
|
|
->where('u.adresse = :address_id');
|
|
$values = ['address_id' => $addressId];
|
|
|
|
return $this->queryAccount($query, $values);
|
|
} catch (Exception $e) {
|
|
throw new GoogleAccountGatewayException($e->getMessage(), $e->getCode(), $e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $accountId
|
|
*
|
|
* @throws NoAccessTokenException
|
|
*
|
|
* @return GoogleAccessTokenData
|
|
*/
|
|
public function getAccessToken(int $accountId): GoogleAccessTokenData
|
|
{
|
|
$query = $this->buildTokenQuery()
|
|
->where('gt.google_account_id = :account_id');
|
|
$values = ['account_id' => $accountId];
|
|
$token = $this->queryToken($query, $values);
|
|
if ($token === null) {
|
|
throw new NoAccessTokenException(
|
|
sprintf('No access token for account "%s" available.', $accountId)
|
|
);
|
|
}
|
|
|
|
return $token;
|
|
}
|
|
|
|
/**
|
|
* @param int $accountId
|
|
* @param string $scope
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function hasAccountScope(int $accountId, string $scope): bool
|
|
{
|
|
$scopes = $this->getScopes($accountId);
|
|
if (in_array($scope, $scopes, true)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param int $accountId
|
|
*
|
|
* @return string[] available scopes of the account
|
|
*/
|
|
public function getScopes(int $accountId): array
|
|
{
|
|
$sql = 'SELECT gs.id, gs.scope FROM `google_account_scope` AS `gs` WHERE gs.google_account_id = :account_id';
|
|
$pairs = $this->db->fetchPairs($sql, ['account_id' => $accountId]);
|
|
if (!is_array($pairs) || count($pairs) === 0) {
|
|
return [];
|
|
}
|
|
|
|
return array_values($pairs);
|
|
}
|
|
|
|
/**
|
|
* Will be removed after Dec 31. 2020
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @codeCoverageIgnore
|
|
*
|
|
* @return GoogleAccountData
|
|
*/
|
|
public function getCloudPrintAccount(): GoogleAccountData
|
|
{
|
|
$accounts = $this->getAccountsByScope(GoogleScope::CLOUDPRINT);
|
|
if (count($accounts) < 1) {
|
|
throw new GoogleAccountNotFoundException('No cloud printing account available.');
|
|
}
|
|
|
|
return $accounts[0];
|
|
}
|
|
|
|
/**
|
|
* @param int $accountId
|
|
*
|
|
* @return GoogleAccountPropertyCollection
|
|
*/
|
|
public function getAccountProperties(int $accountId): GoogleAccountPropertyCollection
|
|
{
|
|
$sql = 'SELECT gp.id, gp.google_account_id, gp.varname, gp.value
|
|
FROM `google_account_property` AS `gp`
|
|
WHERE gp.google_account_id = :account_id';
|
|
$result = $this->db->fetchAll($sql, ['account_id'=> $accountId]);
|
|
if (!is_array($result) || count($result) === 0) {
|
|
return new GoogleAccountPropertyCollection([]);
|
|
}
|
|
$properties = [];
|
|
foreach ($result as $row) {
|
|
$properties[] = GoogleAccountPropertyValue::fromDbState($row);
|
|
}
|
|
|
|
return new GoogleAccountPropertyCollection($properties);
|
|
}
|
|
|
|
/**
|
|
* @return SelectQuery
|
|
*/
|
|
private function buildAccountQuery(): SelectQuery
|
|
{
|
|
return $this->db->select()
|
|
->cols(
|
|
[
|
|
'ga.id',
|
|
'ga.user_id',
|
|
'ga.refresh_token',
|
|
'ga.identifier',
|
|
]
|
|
)
|
|
->from('google_account AS ga');
|
|
}
|
|
|
|
/**
|
|
* @param SelectQuery $query
|
|
* @param array $bindValues
|
|
*
|
|
* @return GoogleAccountData|null
|
|
*/
|
|
private function queryAccount(SelectQuery $query, $bindValues = []): ?GoogleAccountData
|
|
{
|
|
$sql = $query->getStatement();
|
|
$resultSet = $this->db->fetchRow($sql, $bindValues);
|
|
if (empty($resultSet)) {
|
|
return null;
|
|
}
|
|
|
|
return GoogleAccountData::fromDbState($resultSet);
|
|
}
|
|
|
|
/**
|
|
* @return SelectQuery
|
|
*/
|
|
private function buildTokenQuery(): SelectQuery
|
|
{
|
|
return $this->db->select()
|
|
->cols(
|
|
[
|
|
'gt.google_account_id',
|
|
'gt.token',
|
|
'gt.expires',
|
|
]
|
|
)
|
|
->from('google_access_token AS gt');
|
|
}
|
|
|
|
/**
|
|
* @param SelectQuery $query
|
|
* @param array $bindValues
|
|
*
|
|
* @return GoogleAccessTokenData|null
|
|
*/
|
|
private function queryToken(SelectQuery $query, $bindValues = []): ?GoogleAccessTokenData
|
|
{
|
|
$sql = $query->getStatement();
|
|
$resultSet = $this->db->fetchRow($sql, $bindValues);
|
|
if (empty($resultSet)) {
|
|
return null;
|
|
}
|
|
|
|
return GoogleAccessTokenData::fromDbState($resultSet);
|
|
}
|
|
}
|