o365-2.0.3/src/GraphService.php
src/GraphService.php
<?php
namespace Drupal\o365;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\externalauth\AuthmapInterface;
use GuzzleHttp\Exception\ClientException;
use Microsoft\Graph\Graph;
use Microsoft\Graph\Http\GraphCollectionRequest;
/**
* This is the GraphService.
*
* The main service that gets and sets data in Microsoft 365.
*/
class GraphService {
/**
* Drupal\o365\AuthenticationServiceInterface definition.
*/
protected AuthenticationServiceInterface $authService;
/**
* The logger service.
*/
protected O365LoggerServiceInterface $messenger;
/**
* The cache backend service.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected CacheBackendInterface $cacheBackend;
/**
* The modules logger.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected LoggerChannelInterface $logger;
/**
* The externalauth authmap service.
*
* @var \Drupal\externalauth\AuthmapInterface
*/
protected AuthmapInterface $authmap;
/**
* The current user account.
*/
protected AccountProxyInterface $currentUser;
/**
* The timeout used in calls to the Graph API.
*
* @var int
*/
private int $timeout = 1000;
/**
* Constructs a new GraphService object.
*
* @param \Drupal\o365\AuthenticationServiceInterface $authenticationService
* The AuthenticationServiceInterface definition.
* @param \Drupal\o365\O365LoggerServiceInterface $messenger
* The O365LoggerServiceInterface definition.
* @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend
* The CacheBackendInterface definition.
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerChannelFactory
* The logger channel factory. Used to log to the watchdog.
* @param \Drupal\externalauth\AuthmapInterface $authmap
* The externalauth authmap service.
* @param \Drupal\Core\Session\AccountProxyInterface $currentUser
* The current user account.
*/
public function __construct(AuthenticationServiceInterface $authenticationService, O365LoggerServiceInterface $messenger, CacheBackendInterface $cacheBackend, LoggerChannelFactoryInterface $loggerChannelFactory, AuthmapInterface $authmap, AccountProxyInterface $currentUser) {
$this->authService = $authenticationService;
$this->messenger = $messenger;
$this->cacheBackend = $cacheBackend;
$this->logger = $loggerChannelFactory->get('o365');
$this->authmap = $authmap;
$this->currentUser = $currentUser;
}
/**
* Get data from the MS GraphAPI.
*
* @param string $endpoint
* The graph endpoint we want data from.
* @param string $type
* The type of request we want to do.
* @param bool $raw
* This determines if we want a raw body or not.
* @param bool|string $version
* The version of the graph api that is used.
* @param bool|string $returnType
* The return type we want to get.
* @param array $headers
* An array of headers to send.
*
* @return mixed
* The data retrieved from the Graph API.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException|\GuzzleHttp\Exception\GuzzleException|\Microsoft\Graph\Exception\GraphException
*/
public function getGraphData(string $endpoint, string $type = 'GET', bool $raw = FALSE, bool|string $version = FALSE, bool|string $returnType = FALSE, array $headers = []): mixed {
$authMapUser = $this->authmap->get($this->currentUser->getAccount()
->id(), 'o365_sso');
if (!$this->currentUser->isAnonymous() && !$authMapUser) {
return [];
}
return $this->getData($endpoint, $type, $raw, $version, [], $returnType, $headers);
}
/**
* Send data to the MS GraphAPI.
*
* @param string $endpoint
* The graph endpoint we want data from.
* @param mixed $data
* Sent data.
* @param string $type
* The type of request we want to do.
* @param bool $raw
* This determines if we want a raw body or not.
* @param bool|string $version
* The version of the graph api that is used.
* @param bool|string $returnType
* The return type we want to get.
* @param array $headers
* An array of headers to send.
*
* @return mixed
* The data retrieved from the Graph API.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException|\GuzzleHttp\Exception\GuzzleException
* @throws \Microsoft\Graph\Exception\GraphException
*/
public function sendGraphData(string $endpoint, mixed $data = [], string $type = 'POST', bool $raw = FALSE, bool|string $version = FALSE, bool|string $returnType = FALSE, array $headers = []): mixed {
$authMapUser = $this->authmap->get($this->currentUser->getAccount()
->id(), 'o365_sso');
if (!$this->currentUser->isAnonymous() && !$authMapUser) {
return [];
}
return $this->getData($endpoint, $type, $raw, $version, $data, $returnType, $headers);
}
/**
* Generic method to get or send data to the Graph endpoints.
*
* @param string $endpoint
* The graph endpoint we want data from.
* @param string $type
* The type of request we want to do.
* @param bool $raw
* This determines if we want a raw body or not.
* @param bool|string $version
* The version of the graph api that is used.
* @param mixed $data
* Sent data.
* @param bool|string $returnType
* The return type we want to get.
* @param array $headers
* An array of headers to send.
*
* @return mixed
* The retrieved data from the GRAPH API.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException|\Microsoft\Graph\Exception\GraphException
*/
private function getData(string $endpoint, string $type = 'GET', bool $raw = FALSE, bool|string $version = FALSE, mixed $data = [], bool|string $returnType = FALSE, array $headers = []): mixed {
// Get the data from the Graph API.
try {
$graph = new Graph();
if ($version) {
$graph->setApiVersion($version);
}
$accessToken = $this->authService->getAccessToken();
$graph->setAccessToken($accessToken);
if ($type === 'POST' || $type === 'PUT' || $type === 'PATCH') {
$request = $graph->createRequest($type, $endpoint)
->addHeaders($headers)
->setTimeout($this->getTimeout())
->attachBody($data);
if ($returnType) {
$request->setReturnType($returnType);
return $request->execute();
}
$request = $request->execute();
}
elseif ($type === 'UPLOAD') {
$request = $graph->createRequest('PUT', $endpoint)
->addHeaders($headers);
if ($returnType) {
$request->setReturnType($returnType);
return $request->upload($data);
}
$request->upload($data);
}
else {
$request = $graph->createRequest($type, $endpoint)
->addHeaders($headers);
if ($returnType) {
$request->setReturnType($returnType);
return $request->execute();
}
$request = $request->execute();
}
// Get the return values.
$return = $request->getBody();
if ($raw) {
$return = $request->getRawBody();
}
return $return;
}
catch (ClientException $e) {
// Log the error message.
// If error is about a missing profile image, don't log it.
if (!str_contains($e->getMessage(), 'Microsoft.Fast.Profile.Core.Exception.ImageNotFoundException')) {
$this->logger->error($e->getMessage());
}
}
return FALSE;
}
/**
* Get a collection of data.
*
* @param string $endpoint
* The graph endpoint we want data from.
* @param bool|string $returnType
* The return type we want to get.
* @param bool|string $version
* The version of the graph api that is used.
*
* @return false|\Microsoft\Graph\Http\GraphCollectionRequest
* The collection request.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
* @throws \Microsoft\Graph\Exception\GraphException
*/
public function getCollectionData(string $endpoint, bool|string $returnType = FALSE, bool|string $version = FALSE): GraphCollectionRequest|bool {
try {
$graph = new Graph();
if ($version) {
$graph->setApiVersion($version);
}
$accessToken = $this->authService->getAccessToken();
$graph->setAccessToken($accessToken);
$request = $graph->createCollectionRequest('GET', $endpoint);
if ($returnType) {
$request->setReturnType($returnType);
}
return $request;
}
catch (ClientException $e) {
$this->logger->error($e->getMessage());
}
return FALSE;
}
/**
* Determine the office user ID.
*
* @return bool|string
* The ID or FALSE if not logged in via Office.
*/
public function getCurrentUserId(): bool|string {
return $this->authService->checkForOfficeLogin();
}
/**
* Get the Graph API timeout.
*
* @return int
* The timeout in seconds.
*/
public function getTimeout(): int {
return $this->timeout;
}
/**
* Set the Graph API timeout.
*
* @param int $timeout
* The timeout amount in seconds.
*/
public function setTimeout(int $timeout): void {
$this->timeout = $timeout;
}
}
