o365-2.0.3/modules/o365_groups/src/GroupsService.php
modules/o365_groups/src/GroupsService.php
<?php
namespace Drupal\o365_groups;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\o365\GraphService;
use Microsoft\Graph\Model\Channel;
use Microsoft\Graph\Model\Group;
/**
* Service used to do all kinds of stuff with groups and teams.
*/
class GroupsService {
/**
* The o365.graph service.
*
* @var \Drupal\o365\GraphService
*/
protected GraphService $o365Graph;
/**
* The cache backend.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected CacheBackendInterface $cacheBackend;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected AccountInterface $currentUser;
/**
* List of all teams.
*
* @var array
*/
protected array $teams = [];
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected Connection $connection;
/**
* The default endpoint for getting a list of teams.
*
* @var string
*/
protected string $getTeamsEndpoint = "/me/joinedTeams";
/**
* Constructs a GroupsService object.
*
* @param \Drupal\o365\GraphService $o365_graph
* The o365.graph service.
* @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend
* The cache backend.
* @param \Drupal\Core\Session\AccountProxyInterface $accountProxy
* The account proxy.
* @param \Drupal\Core\Database\Connection $connection
* The database connection.
*/
public function __construct(GraphService $o365_graph, CacheBackendInterface $cacheBackend, AccountProxyInterface $accountProxy, Connection $connection) {
$this->o365Graph = $o365_graph;
$this->cacheBackend = $cacheBackend;
$this->currentUser = $accountProxy->getAccount();
$this->connection = $connection;
}
/**
* Get all the available groups from teams.
*
* @return array
* The list of available teams.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
*/
public function getGroupsFromTeams(): array {
$this->getTeamsFromGraph();
$teams = [];
foreach ($this->teams as $id => $name) {
$teams[$id] = $name;
}
// Sort on value.
asort($teams);
return $teams;
}
/**
* Get a list of all groups in Microsoft 365.
*
* @param bool|string $endpoint
* The endpoint string containing the skipToken or FALSE for default.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
*/
protected function getTeamsFromGraph(bool|string $endpoint = FALSE): void {
$cid = 'getTeamsFromGraph::' . $this->currentUser->id();
$cache = $this->cacheBackend->get($cid);
$teams = [];
if (!$cache) {
try {
if (!$endpoint) {
$endpoint = $this->getTeamsEndpoint;
}
$data = $this->o365Graph->getGraphData($endpoint, 'GET', FALSE, FALSE, Group::class);
if ($data) {
/** @var \Microsoft\Graph\Model\Group $group */
foreach ($data as $group) {
$channelEndpoint = '/teams/' . $group->getId() . '/channels';
$groupName = $group->getDisplayName();
$channels = $this->o365Graph->getGraphData($channelEndpoint, 'GET', FALSE, FALSE, Channel::class);
if ($channels) {
/** @var \Microsoft\Graph\Model\Channel $channel */
foreach ($channels as $channel) {
$key = $group->getId() . '|||' . $channel->getId();
$teams[$key] = $groupName . ' - ' . $channel->getDisplayName();
}
}
}
}
$expireDate = strtotime('+4 hours');
$this->cacheBackend->set($cid, $teams, $expireDate);
}
finally {
$this->teams = $teams;
}
}
else {
$this->teams = $cache->data;
}
}
/**
* Generate a link to a team channel based on the ID.
*
* @param int $gid
* The group ID.
*
* @return string|false
* The URL to the team or FALSE.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
*/
public function generateTeamChannelLink(int $gid): bool|string {
if ($this->o365Graph->getCurrentUserId()) {
$data = $this->getTeamsUuidForGroup($gid);
if ($data) {
// Explode the ID on the 3 pipes.
$ids = explode('|||', $data['uuid']);
if (count($ids) > 1) {
$endpoint = '/teams/' . $ids[0] . '/channels/' . $ids[1];
/** @var \Microsoft\Graph\Model\Channel $channel */
$channel = $this->o365Graph->getGraphData($endpoint, 'GET', FALSE, FALSE, Channel::class);
if ($channel) {
return $channel->getWebUrl();
}
}
}
}
return FALSE;
}
/**
* Get the saved teams UUID from the database, or FALSE.
*
* @param int $gid
* The group ID.
* @param bool $onlyUuid
* If we only want to return the UUID.
*
* @return mixed
* The data from the database or FALSE.
*/
public function getTeamsUuidForGroup(int $gid, $onlyUuid = FALSE): mixed {
$result = $this->connection->select('o365_groups_teams', 't')
->fields('t', ['gid', 'uuid'])
->condition('gid', $gid)
->execute();
$assoc = $result->fetchAssoc();
if ($onlyUuid && $assoc) {
return $assoc['uuid'];
}
return $assoc;
}
/**
* Save the teams UUID in the database.
*
* @param string $uuid
* The teams UUID.
* @param int $gid
* The group ID.
*
* @throws \Exception
*/
public function saveTeamsUuidForGroup(string $uuid, int $gid): void {
// Create a new row in our table.
if (!$this->getTeamsUuidForGroup($gid)) {
$this->connection->insert('o365_groups_teams')
->fields([
'gid' => $gid,
'uuid' => $uuid,
])
->execute();
}
else {
// Update the existing row or delete the row when UUID is empty.
if (empty($uuid)) {
$this->connection->delete('o365_groups_teams')
->condition('gid', $gid)
->execute();
}
else {
$this->connection->update('o365_groups_teams')
->fields([
'uuid' => $uuid,
])
->condition('gid', $gid)
->execute();
}
}
}
}
