You are here

asset_injector.module in Asset Injector 8

Same filename and directory in other branches
  1. 8.2 asset_injector.module

Contains module asset_injector.

File

asset_injector.module
View source
<?php

/**
 * @file
 * Contains module asset_injector.
 */
use Drupal\asset_injector\AssetFileStorage;
use Drupal\asset_injector\AssetInjectorInterface;
use Drupal\Core\Config\Entity\ConfigEntityType;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\editor\Entity\Editor;

/**
 * Implements hook_help().
 */
function asset_injector_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.asset_injector':
      $output = '<p>' . t('Use Asset injector rules to add small snippets of code to the page output when specific criteria are met. For example, a simple rule could float a particular div to the right on node editing pages.') . '</p>';
      return $output;
    default:
  }
}

/**
 * Implements hook_entity_type_build().
 *
 * Mark our entities for use in @see asset_injector_get_entity_types().
 * This way contrib modules can add additional assets by implementing
 * \Drupal\asset_injector\AssetInjectorInterface.
 */
function asset_injector_entity_type_build(array &$entity_types) {
  foreach ($entity_types as $entity_type_id => $entity_type) {
    if ($entity_type instanceof ConfigEntityType) {
      $interfaces = class_implements($entity_type
        ->getClass());
      if (isset($interfaces[AssetInjectorInterface::class])) {

        // Mark as ours.
        $entity_type
          ->set('asset_injector_entity_type', TRUE);

        // Add our duplicate-form.
        $path = $entity_type
          ->getLinkTemplate('canonical');
        $entity_type
          ->setLinkTemplate('duplicate-form', "{$path}/duplicate");
      }
    }
  }
}

/**
 * Implements hook_css_alter().
 */
function asset_injector_css_alter(array &$css, AttachedAssetsInterface $assets) {
  foreach ($css as $key => &$item) {
    if (strpos($key, 'asset_injector') !== FALSE) {
      $item['group'] = 999;
    }
  }
}

/**
 * Implements hook_ckeditor_css_alter().
 */
function asset_injector_ckeditor_css_alter(array &$css, Editor $editor) {
  foreach (asset_injector_get_assets() as $asset) {
    if ($asset
      ->extension() == 'css' && $asset
      ->isActive()) {
      $css[] = $asset
        ->internalFileUri();
    }
  }
}

/**
 * Implements hook_library_info_build().
 *
 * Map the library IDs defined in @see asset_injector_page_attachments() to the
 * actual assets. Note that drupal prefixes the IDs with our module name so we
 * must not do that here.
 */
function asset_injector_library_info_build() {
  $libraries = [];
  foreach (asset_injector_get_assets() as $asset) {
    $libraries[$asset
      ->libraryNameSuffix()] = $asset
      ->libraryInfo();
  }
  \Drupal::moduleHandler()
    ->alter('asset_injector_library_info_build', $libraries);
  return $libraries;
}

/**
 * Implements hook_page_attachments().
 *
 * Give the render system the IDs of the curently active assets (that may depend
 * on the curent page and other context - think config overrides). These IDs are
 * mapped to the actual assets in @see asset_injector_library_info_build().
 * Note that the IDs are namespaced with our module name.
 *
 * Concerning cache contexts: The config override system may introduce
 * additional cache contexts to aur assets. Think css that varies by domain.
 * By adding our assets as cacheble dependencies all contexts they may carry
 * apply to the rendered result.
 *
 * Note that the list_cache_tags (library_info) are not added here and need not,
 * as tha caller already does it. Setting asset entityies' list_cache_tags to
 * library_info makes the library-info invalidate on asset change.
 * While changing and deleting of assets will trigger invalidation by their
 * individual cache tags, the list cache tags guarantees invalidation on new
 * asset creation.
 */
function asset_injector_page_attachments(array &$attachments) {

  /** @var RendererInterface $renderer */
  $renderer = \Drupal::service('renderer');
  foreach (asset_injector_get_assets() as $asset) {
    if ($asset
      ->isActive()) {
      $attachments['#attached']['library'][] = 'asset_injector/' . $asset
        ->libraryNameSuffix();
      $renderer
        ->addCacheableDependency($attachments, $asset);
    }
  }
}

/**
 * Get all available assets.
 *
 * @return \Drupal\asset_injector\AssetInjectorInterface[]
 *   Assets from css & js injectors.
 */
function asset_injector_get_assets() {

  /** @var EntityTypeManagerInterface $entity_type_manager */
  $entity_type_manager = \Drupal::entityTypeManager();
  $assets = [];
  foreach (asset_injector_get_entity_types() as $entity_type_id => $entity_type) {
    $entity_type_storage = $entity_type_manager
      ->getStorage($entity_type_id);
    $asset_ids = $entity_type_storage
      ->getQuery()
      ->execute();
    foreach ($entity_type_storage
      ->loadMultiple($asset_ids) as $asset) {
      $assets[] = $asset;
    }
  }
  return $assets;
}

/**
 * Get asset entity types.
 *
 * @return array
 *   Keyed array of entities defined as asset injector types.
 *
 * @see asset_injector_entity_type_build()
 */
function asset_injector_get_entity_types() {
  $asset_entity_types =& drupal_static(__FUNCTION__);
  if (!isset($asset_entity_types)) {
    $entity_types = \Drupal::entityTypeManager()
      ->getDefinitions();
    $asset_entity_types = [];
    foreach ($entity_types as $entity_type_id => $entity_type) {
      if ($entity_type
        ->get('asset_injector_entity_type')) {
        $asset_entity_types[$entity_type_id] = $entity_type;
      }
    }
  }
  return $asset_entity_types;
}

/**
 * Implements hook_cache_flush().
 *
 * Delete all asset files.
 */
function asset_injector_cache_flush() {
  AssetFileStorage::deleteAllFiles();
}