o365-2.0.3/modules/o365_teams/src/O365TeamsSendMessageService.php
modules/o365_teams/src/O365TeamsSendMessageService.php
<?php
namespace Drupal\o365_teams;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\o365\GraphService;
use Microsoft\Graph\Model\User;
/**
* This service is used to send messages to users / channels.
*/
class O365TeamsSendMessageService {
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* The o365 graph service.
*
* @var \Drupal\o365\GraphService
*/
protected $graphService;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs an O365TeamsSendMessageService object.
*
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
* @param \Drupal\o365\GraphService $graphService
* The o365 graph service.
* @param \Drupal\Core\Session\AccountProxyInterface $accountProxy
* The current user.
*/
public function __construct(MessengerInterface $messenger, GraphService $graphService, AccountProxyInterface $accountProxy) {
$this->messenger = $messenger;
$this->graphService = $graphService;
$this->currentUser = $accountProxy->getAccount();
}
/**
* Send a message to a single user.
*
* @param string $recipient
* The recipient of the message.
* @param string $message
* The actual message we want to send.
*
* @return mixed|null
* The recipients email address so we can create a link to the Teams chat.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
*/
public function sendMessageToUser($recipient, $message) {
$userPrincipalName = self::extractUserPrincipalNameFromAutocompleteInput($recipient);
$chatId = $this->createOneOnOneChat($userPrincipalName);
if ($chatId) {
$endpoint = '/chats/' . $chatId . '/messages';
$jsonData = [
'body' => [
'content' => Xss::filter($message),
],
];
$return = $this->graphService->sendGraphData($endpoint, $jsonData);
if ($return) {
$message = new TranslatableMarkup('Your message has been sent to @recipient', ['@recipient' => $recipient]);
$this->messenger->addMessage($message);
}
else {
$message = new TranslatableMarkup('Something went wrong sending your message to @recipient. Please try again later.', ['@recipient' => $recipient]);
$this->messenger->addError($message);
}
}
else {
$message = new TranslatableMarkup('We could not create the chat, please try again later.');
$this->messenger->addError($message);
}
return $userPrincipalName;
}
/**
* Get the user data of a recipient.
*
* @param string $recipient
* The recipients usePrincipalName (mail address).
*
* @return \Microsoft\Graph\Model\User|false
* The recipient user data.
*/
public function getUserDataFromRecipient($recipient) {
$endpoint = '/users/' . $recipient;
/** @var \Microsoft\Graph\Model\User $userData */
$userData = $this->graphService->getGraphData($endpoint, 'GET', FALSE, FALSE, User::class);
return $userData;
}
/**
* Create a chat we can use to send the message to.
*
* @param string $userPrincipalName
* The recipient of the message.
*
* @return false|string
* The chat ID or FALSE.
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
*/
protected function createOneOnOneChat($userPrincipalName) {
$members = [
$userPrincipalName,
$this->currentUser->getEmail(),
];
$jsondata = [
'chatType' => 'oneOnOne',
'members' => [],
];
foreach ($members as $member) {
$jsondata['members'][] = [
'@odata.type' => '#microsoft.graph.aadUserConversationMember',
'roles' => ['owner'],
'user@odata.bind' => 'https://graph.microsoft.com/v1.0/users(\'' . $member . '\')',
];
}
$chat = $this->graphService->sendGraphData('/chats', $jsondata);
if ($chat) {
return $chat['id'];
}
return FALSE;
}
/**
* Extracts the user principal name from the autocompletion result.
*
* @param string $input
* The input coming from the autocompletion result.
*
* @return mixed|null
* An userPrincipalName or NULL if the input does not contain one.
*/
private static function extractUserPrincipalNameFromAutocompleteInput($input) {
$match = NULL;
// Get 'name (userPrincipalName)', match the ID from inside the parentheses.
if (preg_match("/.+\s\(([^\)]+)\)/", $input, $matches)) {
$match = $matches[1];
}
return $match;
}
}
