You are here

responsive_favicons.module in Responsive Favicons 8

Same filename and directory in other branches
  1. 7 responsive_favicons.module

File

responsive_favicons.module
View source
<?php

/**
 * @file
 * Contains responsive_favicons.module.
 */
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Render\Markup;
use Drupal\Core\StreamWrapper\PublicStream;

/**
 * Implements hook_help().
 */
function responsive_favicons_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {

    // Main module help for the responsive_favicons module.
    case 'help.page.responsive_favicons':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('This module adds the favicons generated by http://realfavicongenerator.net/ to your site. The responsive name comes from the fact that many devices are catered for including iPhone, Android, iPad, other tablets and dektops.') . '</p>';
      return $output;
    default:
  }
}

/**
 * Implements hook_page_attachments().
 *
 * Adds responsive favicons to HTML head. A trailing newline is added to ensure
 * the next tag in the HTML head section starts on the next line.
 */
function responsive_favicons_page_attachments(array &$page) {
  $tags = responsive_favicons_load_all_icons();
  if (!empty($tags['found'])) {
    $html = [
      '#tag' => 'meta',
      '#attributes' => [
        'name' => 'favicon-generator',
        'content' => 'Drupal responsive_favicons + realfavicongenerator.net',
      ],
      // This seems like the only way to inject raw HTML into the head section
      // of Drupal 8.
      // @todo find a way to make this better.
      '#prefix' => Markup::create(implode(PHP_EOL, $tags['found']) . PHP_EOL),
      '#suffix' => '',
    ];
    $page['#attached']['html_head'][] = [
      $html,
      'responsive_favicons',
    ];
  }
}

/**
 * Implements hook_page_attachments_alter().
 *
 * Remove the stock Drupal favicon if it is present.
 */
function responsive_favicons_page_attachments_alter(array &$attachments) {
  $config = \Drupal::config('responsive_favicons.settings');
  if ($config
    ->get('remove_default') && isset($attachments['#attached']['html_head_link'])) {
    foreach ($attachments['#attached']['html_head_link'] as $key => $config) {
      if (isset($config[0]['rel']) && $config[0]['rel'] === 'shortcut icon') {
        unset($attachments['#attached']['html_head_link'][$key]);
      }
    }
  }
}

/**
 * Load the responsive favicons that are valid.
 */
function responsive_favicons_load_all_icons() {
  $icons =& drupal_static(__FUNCTION__);
  if (!isset($icons)) {
    $config = \Drupal::config('responsive_favicons.settings');
    $cid = 'responsive_favicons:icons';
    if ($cached = \Drupal::cache()
      ->get($cid)) {
      $icons = $cached->data;
    }
    else {
      $tags = $config
        ->get('tags');
      if (empty($tags)) {
        $icons = [
          'found' => [],
          'missing' => [],
        ];
      }
      else {
        $html = implode(PHP_EOL, $tags);
        $icons = _responsive_favicons_validate_tags($html);
        if (empty($icons['missing'])) {
          \Drupal::cache()
            ->set($cid, $icons);
        }
      }
    }
  }
  return $icons;
}

/**
 * Helper function to check whether responsive favicon files exist and are
 * readable. This function also strips any pasted content that is not a link
 * or a meta tag.
 *
 * @param string $html
 *   html tag
 * @return array $missing_files
 */
function _responsive_favicons_validate_tags($html) {
  global $base_path;
  $found = [];
  $missing = [];
  $dom = new DOMDocument();
  $dom
    ->loadHTML($html);

  // DRUPAL_ROOT contains the sub directory of the Drupal install (if present),
  // in our case we do not want this as $file_path already contains this.
  $docroot = preg_replace('/' . preg_quote($base_path, '/') . '$/', '/', DRUPAL_ROOT);

  // Find all the apple touch icons.
  $tags = $dom
    ->getElementsByTagName('link');
  foreach ($tags as $tag) {
    $url_path = _responsive_favicons_normalise_path($tag
      ->getAttribute('href'));
    $file_path = parse_url($url_path, PHP_URL_PATH);
    $tag
      ->setAttribute('href', $url_path);
    if (file_exists($docroot . $file_path) && is_readable($docroot . $file_path)) {
      $found[] = $dom
        ->saveXML($tag);
    }
    else {
      $missing[] = $dom
        ->saveXML($tag);
    }
  }

  // Find any Windows 8 meta tags.
  $tags = $dom
    ->getElementsByTagName('meta');
  foreach ($tags as $tag) {
    $name = $tag
      ->getAttribute('name');

    // We only validate the image file.
    if ($name === 'msapplication-TileImage') {
      $url_path = _responsive_favicons_normalise_path($tag
        ->getAttribute('content'));
      $file_path = parse_url($url_path, PHP_URL_PATH);
      $tag
        ->setAttribute('content', $url_path);
      if (file_exists($docroot . $file_path) && is_readable($docroot . $file_path)) {
        $found[] = $dom
          ->saveXML($tag);
      }
      else {
        $missing[] = $dom
          ->saveXML($tag);
      }
    }
    else {
      $found[] = $dom
        ->saveXML($tag);
    }
  }
  return [
    'found' => $found,
    'missing' => $missing,
  ];
}

/**
 * Help to normalise the path to the icons.
 *
 * @param $file_path
 *   The filename of the icon.
 * @return string
 *   The full relative path to the icon within public files.
 */
function _responsive_favicons_normalise_path($file_path) {
  $config = \Drupal::config('responsive_favicons.settings');

  // Remove absolute URLs.
  if (UrlHelper::isExternal($file_path)) {
    $file_path = str_replace(\Drupal::request()
      ->getSchemeAndHttpHost(), '', $file_path);
  }
  if ($config
    ->get('path_type') === 'upload') {
    return '/' . PublicStream::basePath() . '/' . $config
      ->get('path') . $file_path;
  }
  else {
    return $config
      ->get('path') . $file_path;
  }
}

Functions

Namesort descending Description
responsive_favicons_help Implements hook_help().
responsive_favicons_load_all_icons Load the responsive favicons that are valid.
responsive_favicons_page_attachments Implements hook_page_attachments().
responsive_favicons_page_attachments_alter Implements hook_page_attachments_alter().
_responsive_favicons_normalise_path Help to normalise the path to the icons.
_responsive_favicons_validate_tags Helper function to check whether responsive favicon files exist and are readable. This function also strips any pasted content that is not a link or a meta tag.