sitewide_alerts-1.0.0/src/SiteAlertService.php
src/SiteAlertService.php
<?php
namespace Drupal\sitewide_alerts;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheFactoryInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Security\TrustedCallbackInterface;
use Drupal\Core\State\State;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\taxonomy\Entity\Term;
/**
* Site Alert Service.
*
* @package Drupal\sitewide_alerts
*/
class SiteAlertService implements TrustedCallbackInterface {
use MessengerTrait;
use StringTranslationTrait;
/**
* The cache backend.
*/
private CacheBackendInterface $cache;
/**
* The config.
*/
private ImmutableConfig $config;
/**
* The time.
*/
private TimeInterface $time;
/**
* The entity type manager.
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The state.
*/
protected State $state;
/**
* The admin context.
*/
protected AdminContext $adminContext;
/**
* The database.
*/
protected Connection $database;
/**
* The module handler.
*/
protected ModuleHandler $moduleHandler;
/**
* SiteAlertService constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
* The config.
* @param \Drupal\Core\Cache\CacheFactoryInterface $cache
* The cache factory.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\State\State $state
* The state.
* @param \Drupal\Core\Routing\AdminContext $admin_context
* The admin context.
* @param \Drupal\Core\Database\Connection $database
* The database connection.
* @param \Drupal\Core\Extension\ModuleHandler $module_handler
* The module handler.
*/
public function __construct(
ConfigFactoryInterface $config,
CacheFactoryInterface $cache,
TimeInterface $time,
EntityTypeManagerInterface $entity_type_manager,
State $state,
AdminContext $admin_context,
Connection $database,
ModuleHandler $module_handler
) {
$this->cache = $cache->get('sitewide_alerts');
$this->config = $config->get('sitewide_alerts.settings');
$this->time = $time;
$this->entityTypeManager = $entity_type_manager;
$this->state = $state;
$this->adminContext = $admin_context;
$this->database = $database;
$this->moduleHandler = $module_handler;
}
/**
* Get the config.
*
* @return \Drupal\Core\Config\ImmutableConfig
* Returns the config.
*/
public function getConfig(): ImmutableConfig {
return $this->config;
}
/**
* Get the state config.
*
* @param array $state_keys
* Array of state keys to fetch.
*
* @return array
* The array of state config values.
*/
public function getStateConfig(array $state_keys = []): array {
return $this->state->getMultiple($state_keys);
}
/**
* Set state configuration data.
*
* @param array $data
* The array of state config.
*/
public function setStateConfig(array $data): void {
$this->state->setMultiple($data);
}
/**
* Get module handler.
*
* @return \Drupal\Core\Extension\ModuleHandler
* Returns the module handler.
*/
public function getModuleHandler(): ModuleHandler {
return $this->moduleHandler;
}
/**
* Get entity type manager.
*
* @return \Drupal\Core\Entity\EntityTypeManagerInterface
* Returns the entity type manager.
*/
public function getEntityTypeManager(): EntityTypeManagerInterface {
return $this->entityTypeManager;
}
/**
* Determine if site alerts are enabled or not.
*
* @return bool
* Returns TRUE if enabled, FALSE otherwise.
*/
public function isEnabled(): bool {
$config = $this->getConfig();
if ($config->get('active')) {
return TRUE;
}
else {
return FALSE;
}
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks(): array {
return [
'preRenderDefaultLink',
'preRenderSiteAlert',
'preRenderSiteAlertType',
];
}
/**
* Get/pre-render default alerts link.
*
* @param string $language
* The current language code.
*
* @return array
* Returns the render array.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityMalformedException
*/
public function preRenderDefaultLink(string $language = 'en'): array {
$build = [];
$alerts_page_nid = $this->getConfig()->get('default_alerts_page');
if (!empty($alerts_page_nid)) {
/** @var \Drupal\node\Entity\Node $node */
$node = $this->entityTypeManager->getStorage('node')->load($alerts_page_nid);
if ($node->isTranslatable() && $node->hasTranslation($language)) {
$node = $node->getTranslation($language);
}
if ($node) {
$build = [
'#type' => 'link',
'#title' => $this->t('Learn more'),
'#url' => $node->toUrl(),
'#attributes' => [
'class' => [
'c-site-alert-default-link',
],
],
'#prefix' => '<div class="field field-site-alert-default-link field__item">',
'#suffix' => '</div>',
];
// Setup cache meta data.
$cacheableMetadata = new CacheableMetadata();
$cacheableMetadata->addCacheableDependency($node);
$cacheableMetadata->applyTo($build);
}
}
return $build;
}
/**
* Get site alert entity by id.
*
* @param int $id
* The site alert entity id.
*
* @return \Drupal\Core\Entity\EntityInterface|null
* Returns the site alert entity.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function getSiteAlert(int $id): ?EntityInterface {
return $this->entityTypeManager->getStorage('site_alert')->load($id);
}
/**
* Get site alert types.
*
* @param string $language
* The current language code.
*
* @return array
* Returns an array of site alert types.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function getSiteAlertTypes(string $language = 'en'): array {
$site_alert_types = [];
// Get the term storage.
$entity_storage = $this->entityTypeManager->getStorage('taxonomy_term');
// Query the terms sorted by weight.
$query_result = $entity_storage->getQuery()
->accessCheck()
->condition('vid', 'site_alert_types')
->sort('weight', 'ASC')
->execute();
// Load the terms.
$terms = $entity_storage->loadMultiple($query_result);
/** @var \Drupal\taxonomy\Entity\Term $term */
foreach ($terms as $term) {
if ($term->isTranslatable()) {
if ($term->hasTranslation($language)) {
$term = $term->getTranslation($language);
}
}
$site_alert_types[$term->id()] = $term;
}
return $site_alert_types;
}
/**
* Get site alerts in order by weight and language.
*
* @param string $language
* The current language code.
*
* @return array
* The array of site alert entities.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function getSiteAlerts(string $language = 'en'): array {
// Get site alerts ordered by weight field.
$query = $this->database->select('site_alert', 's');
$query->addField('s', 'id');
$query->addField('s', 'revision_id');
$query->addJoin('inner', 'site_alert_field_data', 'sf', 'sf.id = s.id AND sf.revision_id = s.revision_id');
// Filter by language code if set.
if (!empty($language)) {
$query->condition('sf.langcode', $language, '=');
}
// Only want published site alerts.
$query->condition('sf.status', 1, '=');
// Order by weight.
$query->orderBy('sf.weight', 'ASC');
// Allow for altering of query.
$this->moduleHandler->invokeAll('sitewide_alerts_alter_query', [&$query]);
// Get results.
$result = $query->execute();
// Get site alert ids.
$ids = [];
while ($row = $result->fetchObject()) {
$ids[$row->revision_id] = $row->id;
}
// Load up site alert entities by ids.
$site_alerts = [];
$entities = $this->entityTypeManager->getStorage('site_alert')->loadMultiple($ids);
/**
* @var \Drupal\sitewide_alerts\Entity\SiteAlert $site_alert
*/
foreach ($entities as $id => $site_alert) {
// Check to see if entity is translatable.
if ($site_alert->isTranslatable()) {
// Check to see if entity has translation.
if ($site_alert->hasTranslation($language)) {
// Has translation, so we return it.
$site_alerts[$id] = $site_alert->getTranslation($language);
}
}
else {
// Not translatable, so we just return it.
$site_alerts[$id] = $site_alert;
}
}
// Allow for altering site alerts.
$this->moduleHandler->invokeAll('sitewide_alerts_alter_alerts', [&$site_alerts]);
return $site_alerts;
}
/**
* Get site alert bar and return render array.
*
* @param string $language
* The current language.
*
* @return array
* Returns the render array.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function getSiteAlertBar(string $language = 'en'): array {
$build = [];
// Check to see if site alerts is enabled.
if ($this->isEnabled()) {
$config = $this->getConfig();
// Not admin route.
if (!$this->adminContext->isAdminRoute()) {
// Set and get default view mode.
$view_mode = 'default';
if (!empty($config->get('default_view_mode'))) {
$view_mode = $config->get('default_view_mode');
}
$build = [
'#theme' => 'site_alerts',
'#view_mode' => $view_mode,
];
// Store alert keys.
$alert_keys = [];
// Get site alerts.
$build['#alerts'] = [];
$site_alerts = $this->getSiteAlerts($language);
/** @var \Drupal\sitewide_alerts\SiteAlertInterface $site_alert */
foreach ($site_alerts as $site_alert) {
$build['#alerts'][] = $this->preRenderSiteAlert($site_alert, $view_mode, $language);
$alert_keys[] = $site_alert->id() . '-' . $site_alert->language()->getId();
}
// Attach drupal settings.
$build['#attached'] = [
'drupalSettings' => [
'sitewide_alerts' => [
'dismissedKeys' => $alert_keys,
'previewMode' => FALSE,
'cookieExpiration' => $this->getSiteAlertExpiration(),
],
],
];
// Setup cache meta data.
$cacheableMetadata = new CacheableMetadata();
$cacheableMetadata->addCacheableDependency($config);
/** @var \Drupal\sitewide_alerts\SiteAlertInterface $site_alert */
foreach ($site_alerts as $site_alert) {
$cacheableMetadata->addCacheableDependency($site_alert);
}
$cacheableMetadata->addCacheTags(['sitewide_alerts']);
$cacheableMetadata->applyTo($build);
}
}
return $build;
}
/**
* Get site alert render array.
*
* @param \Drupal\sitewide_alerts\SiteAlertInterface $site_alert
* The site alert entity.
* @param string $view_mode
* The view mode to render the site alert in.
* @param string $language
* The current language.
*
* @return array
* Returns the render array for site alert.
*/
public function preRenderSiteAlert(SiteAlertInterface $site_alert, string $view_mode = 'default', string $language = 'en'): array {
$view_builder = $this->entityTypeManager->getViewBuilder('site_alert');
return $view_builder->view($site_alert, $view_mode, $language);
}
/**
* Get site alert type render array.
*
* @param \Drupal\taxonomy\Entity\Term $site_alert_type
* The site alert entity.
* @param string $view_mode
* The view mode to render the site alert in.
* @param string $language
* The current language.
*
* @return array
* Returns the render array for site alert type.
*/
public function preRenderSiteAlertType(Term $site_alert_type, string $view_mode = 'default', string $language = 'en'): array {
$view_builder = $this->entityTypeManager->getViewBuilder('taxonomy_term');
return $view_builder->view($site_alert_type, $view_mode, $language);
}
/**
* Get site alert expiration.
*
* @return int|string
* Returns the expiration value for site alert.
*/
public function getSiteAlertExpiration(): int|string {
$config = $this->getConfig();
// Set up cookie expiration value for jQuery cookie function.
switch ($config->get('expiration')) {
case 'year':
$expiration = 365;
break;
case 'month':
$expiration = 30;
break;
case 'week':
$expiration = 7;
break;
case 'day':
$expiration = 1;
break;
default:
$expiration = 'default';
}
return $expiration;
}
}
