View source
<?php
namespace Drupal\sendgrid_integration_reports;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Cache\CacheFactoryInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
class Api {
protected $apiKey = NULL;
protected $bin = 'sendgrid_integration_reports';
protected $messenger;
protected $configFactory;
protected $loggerFactory;
protected $moduleHandler;
protected $cacheFactory;
public function __construct(ConfigFactoryInterface $config_factory, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger_factory, ModuleHandlerInterface $moduleHandler, CacheFactoryInterface $cacheFactory) {
$this->configFactory = $config_factory;
$this->messenger = $messenger;
$this->loggerFactory = $logger_factory;
$this->moduleHandler = $moduleHandler;
$this->cacheFactory = $cacheFactory;
$key_secret = $this->configFactory
->get('sendgrid_integration.settings')
->get('apikey');
if ($this->moduleHandler
->moduleExists('key')) {
$key = \Drupal::service('key.repository')
->getKey($key_secret);
if ($key && $key
->getKeyValue()) {
$this->apiKey = $key
->getKeyValue();
}
}
else {
$this->apiKey = $key_secret;
}
if (empty($this->apiKey)) {
$this->loggerFactory
->get('sendgrid_integration_reports')
->warning(t('SendGrid Module is not setup with API key.'));
$this->messenger
->addWarning('Sendgrid Module is not setup with an API key.');
}
}
protected function setCache($cid, array $data) {
if (!empty($data)) {
$this->cacheFactory
->get($this->bin)
->set($cid, $data);
}
}
protected function getResponse($path, array $query, string $onBehalfOf = '') {
$headers['Authorization'] = 'Bearer ' . $this->apiKey;
if ($onBehalfOf) {
$headers['on-behalf-of'] = $onBehalfOf;
}
$clienttest = new Client([
'base_uri' => 'https://api.sendgrid.com/v3/',
'headers' => $headers,
]);
try {
$response = $clienttest
->get($path, [
'query' => $query,
]);
} catch (ClientException $e) {
$code = Xss::filter($e
->getCode());
$this->loggerFactory
->get('sendgrid_integration_reports')
->error(t('SendGrid Reports module failed to receive data. HTTP Error Code @errno', [
'@errno' => $code,
]));
$this->messenger
->addError(t('SendGrid Reports module failed to receive data. See logs.'));
return FALSE;
}
$body = Xss::filter($response
->getBody());
return json_decode($body);
}
public function getStats($cid, array $categories = [], $start_date = NULL, $end_date = NULL, $refresh = FALSE, $subuser = '') {
if (!$refresh && ($cache = $this->cacheFactory
->get($this->bin)
->get($cid))) {
return $cache->data;
}
if (empty($this->apiKey)) {
return [];
}
$config = $this->configFactory
->get('sendgrid_integration_reports.settings')
->get();
if ($start_date) {
$start_date = date('Y-m-d', strtotime($start_date));
}
else {
$start_date = empty($config['start_date']) ? date('Y-m-d', strtotime('today - 30 days')) : $config['start_date'];
}
if ($end_date) {
$end_date = date('Y-m-d', strtotime($end_date));
}
else {
$end_date = empty($config['end_date']) ? date('Y-m-d', strtotime('today')) : $config['end_date'];
}
$aggregated_by = isset($config['aggregated_by']) ? $config['aggregated_by'] : 'day';
$path = 'stats';
$query = [
'start_date' => $start_date,
'end_date' => $end_date,
'aggregated_by' => $aggregated_by,
];
if ($categories) {
$path = 'categories/stats';
$query['categories'] = $categories;
$query_str = http_build_query($query, NULL, '&', PHP_QUERY_RFC3986);
$query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $query_str);
}
$stats_data = $this
->getResponse($path, $query, $subuser);
if (!$stats_data) {
return [];
}
$data = [];
foreach ($stats_data as $item) {
$data['global'][] = [
'date' => $item->date,
'opens' => $item->stats[0]->metrics->opens,
'processed' => $item->stats[0]->metrics->processed,
'requests' => $item->stats[0]->metrics->requests,
'clicks' => $item->stats[0]->metrics->clicks,
'delivered' => $item->stats[0]->metrics->delivered,
'deferred' => $item->stats[0]->metrics->deferred,
'unsubscribes' => $item->stats[0]->metrics->unsubscribes,
'unsubscribe_drops' => $item->stats[0]->metrics->unsubscribe_drops,
'invalid_emails' => $item->stats[0]->metrics->invalid_emails,
'bounces' => $item->stats[0]->metrics->bounces,
'bounce_drops' => $item->stats[0]->metrics->bounce_drops,
'unique_clicks' => $item->stats[0]->metrics->unique_clicks,
'blocks' => $item->stats[0]->metrics->blocks,
'spam_report_drops' => $item->stats[0]->metrics->spam_report_drops,
'spam_reports' => $item->stats[0]->metrics->spam_reports,
'unique_opens' => $item->stats[0]->metrics->unique_opens,
];
}
$this
->setCache($cid, $data);
return $data;
}
public function getStatsBrowser($subuser = '') {
$cid = 'sendgrid_reports_browsers:' . ($subuser ? $subuser : 'global');
if ($cache = $this->cacheFactory
->get($this->bin)
->get($cid)) {
return $cache->data;
}
if (empty($this->apiKey)) {
return [];
}
$start_date = empty($config['start_date']) ? date('Y-m-d', strtotime('today - 30 days')) : $config['start_date'];
$end_date = empty($config['end_date']) ? date('Y-m-d', strtotime('today')) : $config['end_date'];
$aggregated_by = isset($config['aggregated_by']) ? $config['aggregated_by'] : 'day';
$path = 'browsers/stats';
$query = [
'start_date' => $start_date,
'end_date' => $end_date,
'aggregated_by' => $aggregated_by,
];
$statsdata = $this
->getResponse($path, $query);
if (!$stats_data) {
return [];
}
$data = [];
foreach ($statsdata as $item) {
foreach ($item->stats as $inneritem) {
if (array_key_exists($inneritem->name, $data)) {
$data[$inneritem->name] += $inneritem->metrics->clicks;
}
else {
$data[$inneritem->name] = $inneritem->metrics->clicks;
}
}
}
$this
->setCache($cid, $data);
return $data;
}
public function getStatsDevices($subuser = '') {
$cid = 'sendgrid_reports_devices:' . ($subuser ? $subuser : 'global');
if ($cache = $this->cacheFactory
->get($this->bin)
->get($cid)) {
return $cache->data;
}
if (empty($this->apiKey)) {
return FALSE;
}
$start_date = empty($config['start_date']) ? date('Y-m-d', strtotime('today - 30 days')) : $config['start_date'];
$end_date = empty($config['end_date']) ? date('Y-m-d', strtotime('today')) : $config['end_date'];
$aggregated_by = isset($config['aggregated_by']) ? $config['aggregated_by'] : 'day';
$path = 'devices/stats';
$query = [
'start_date' => $start_date,
'end_date' => $end_date,
'aggregated_by' => $aggregated_by,
];
$statsdata = $this
->getResponse($path, $query);
if (!$stats_data) {
return [];
}
$data = [];
foreach ($statsdata as $item) {
foreach ($item->stats as $inneritem) {
if (array_key_exists($inneritem->name, $data)) {
$data[$inneritem->name] += $inneritem->metrics->opens;
}
else {
$data[$inneritem->name] = $inneritem->metrics->opens;
}
}
}
$this
->setCache($cid, $data);
return $data;
}
public function getSubusers() {
$cid = 'sendgrid_reports_subusers';
if ($cache = $this->cacheFactory
->get($this->bin)
->get($cid)) {
return $cache->data;
}
$path = 'subusers';
$query = [
'limit' => 500,
'offset' => 0,
];
$subusers = [];
do {
$response = $this
->getResponse($path, $query);
$query['offset'] += 500;
$subusers = array_merge($subusers, $response);
} while (!empty($response));
$this
->setCache($cid, $subusers);
return $subusers;
}
public function getBouncesBySubuser($startTime = 0, $endTime = 0, $subuser = '') {
$cid = 'sendgrid_reports_bounces';
if ($cache = $this->cacheFactory
->get($this->bin)
->get($cid)) {
return $cache->data;
}
$path = 'suppression/bounces';
$query = [
'start_time' => $startTime ? $startTime : strtotime('-1 month'),
'end_time' => $endTime ? $endTime : time(),
];
$subusers = $subuser ? [
(object) [
'username' => $subuser,
],
] : $this
->getSubusers();
$bounces = [];
foreach ($subusers as $subuser) {
$username = $subuser->username;
$response = $this
->getResponse($path, $query, $username);
if (!empty($response)) {
$bounces[$username] = $response;
}
}
$this
->setCache($cid, $bounces);
return $bounces;
}
}