progressive_image_loading-8.x-1.x-dev/progressive_image_loading.module
progressive_image_loading.module
<?php
/**
* @file
* Code for the Progressive Image Loading module.
*/
/**
* Implements hook_page_attachments().
*
* Adds the breakpoints of the active theme with their respective media queries,
* we need this relation for responsive background images.
*/
function progressive_image_loading_page_attachments(array &$page) {
$breakpoints = [];
/** @var \Drupal\Core\Theme\ThemeManagerInterface $theme_manager */
$theme_manager = \Drupal::service('theme.manager');
/** @var \Drupal\breakpoint\BreakpointManagerInterface $breakpoint_manager */
$breakpoint_manager = \Drupal::service('breakpoint.manager');
$current_theme = $theme_manager->getActiveTheme()->getName();
foreach ($breakpoint_manager->getBreakpointsByGroup($current_theme) as $id => $breakpoint) {
// This extract the breakpoint machine name, my_theme.xs to xs.
$machine_name = preg_replace('/^' . $current_theme . '\./', '', $id);
$breakpoints[$machine_name] = [
'name' => $machine_name,
'mediaQuery' => $breakpoint->getMediaQuery(),
];
}
$page['#attached']['drupalSettings']['progressiveImageLoading']['breakpoints'] = $breakpoints;
}
/**
* Implements hook_preprocess_HOOK() for case 'image'.
*/
function progressive_image_loading_preprocess_image(&$variables) {
progressive_image_loading_preprocess_hook($variables, 'image');
}
/**
* Implements hook_preprocess_HOOK() for case 'responsive_image'.
*/
function progressive_image_loading_preprocess_responsive_image(&$variables) {
progressive_image_loading_preprocess_hook($variables, 'responsive_image');
}
/**
* Alters the element attributes.
*
* @param array $variables
* An array of variables passed to the preprocess hook.
* @param string $hook
* The name of the hook.
*/
function progressive_image_loading_preprocess_hook(array &$variables, $hook) {
/** @var \Drupal\progressive_image_loading\ProgressiveImageLoadingManagerInterface $manager */
$manager = \Drupal::service('progressive_image_loading.manager');
// Skip if we are on excluded path.
if ($manager->currentPathIsExcluded()) {
return;
}
switch ($hook) {
case 'image':
case 'responsive_image':
// Add the trigger class and the module library.
$variables['attributes']['class'][] = 'progressive-image-loading';
$variables['#attached']['library'][] = 'progressive_image_loading/library';
// Replace src attributes for lazy load.
if (!empty($variables['attributes']['src']) && empty($variables['attributes']['data-src'])) {
$variables['attributes']['data-src'] = $variables['attributes']['src'];
}
if (!empty($variables['attributes']['srcset']) && empty($variables['attributes']['data-srcset'])) {
$variables['attributes']['data-srcset'] = $variables['attributes']['srcset'];
unset($variables['attributes']['srcset']);
}
// Generate a loq quality image placeholder.
$width = $variables['width'] ?? 1;
$height = $variables['height'] ?? 1;
$variables['attributes']['src'] = $manager->createPlaceholder($variables['uri'], $width, $height);
// Replace srcset with data-srcset attributes for lazy load.
if (!empty($variables['sources'])) {
foreach ($variables['sources'] as $source) {
$storage = $source->storage();
$source->setAttribute('data-srcset', $storage['srcset']->value());
$source->removeAttribute('srcset');
}
}
// As our background formatters extend the image ones we need to remove
// the attributes witch are not used in background formatters.
if (in_array('progressive-image-loading-background', $variables['attributes']['class'])) {
$attributes = [
'src', 'data-src', 'data-srcset',
'sizes', 'typeof', 'width', 'height',
];
foreach ($attributes as $attribute) {
if (!empty($variables['attributes'][$attribute])) {
unset($variables['attributes'][$attribute]);
}
}
}
break;
}
}
/**
* Implements hook_theme_suggestions_HOOK_alter() for case 'image'.
*/
function progressive_image_loading_theme_suggestions_image_alter(array &$suggestions, array $variables) {
progressive_image_loading_suggestions_alter($suggestions, $variables, 'image');
}
/**
* Implements hook_theme_suggestions_HOOK_alter() for case 'responsive_image'.
*/
function progressive_image_loading_theme_suggestions_responsive_image_alter(array &$suggestions, array $variables) {
progressive_image_loading_suggestions_alter($suggestions, $variables, 'responsive_image');
}
/**
* Add our custom theme suggestions.
*
* @param array $suggestions
* An array of alternate, more specific names for template files or theme
* functions.
* @param array $variables
* An array of variables passed to the theme suggestion hook.
* @param string $hook
* The name of the hook.
*/
function progressive_image_loading_suggestions_alter(array &$suggestions, array $variables, $hook) {
switch ($hook) {
case 'image':
case 'responsive_image':
if (!empty($variables['attributes']['class']) && in_array('progressive-image-loading-background', $variables['attributes']['class'])) {
$hook = 'background_' . $hook;
}
$suggestions[] = $hook . '__progressive_image_loading';
break;
}
}
/**
* Implements hook_theme_registry_alter().
*/
function progressive_image_loading_theme_registry_alter(&$theme_registry) {
// Prepare the module list adding '_preprocess' suffix for later use.
$themes = array_map(
function ($key) {
return $key . '_preprocess';
},
array_keys(\Drupal::service('theme_handler')->listInfo())
);
// Make our template not depend on any theme, and make sure our preprocess
// functions are executed just before theme preprocess.
foreach (['image', 'responsive_image'] as $theme) {
if (!empty($theme_registry[$theme]['preprocess functions'])) {
$module_functions = $theme_functions = [];
$theme_registry[$theme]['preprocess functions'] = array_diff($theme_registry[$theme]['preprocess functions'], ['progressive_image_loading_preprocess_' . $theme]);
foreach ($theme_registry[$theme]['preprocess functions'] as $function) {
$is_theme = FALSE;
foreach ($themes as $theme_preprocess) {
if (strpos($function, $theme_preprocess) !== FALSE) {
$is_theme = TRUE;
break;
}
}
if ($is_theme) {
$theme_functions[] = $function;
}
else {
$module_functions[] = $function;
}
}
$theme_registry[$theme]['preprocess functions'] = array_merge($module_functions, ['progressive_image_loading_preprocess_image'], $theme_functions);
}
$theme_registry[$theme . '__progressive_image_loading'] = $theme_registry[$theme];
$theme_registry[$theme . '__progressive_image_loading']['template'] = str_replace('_', '-', $theme) . '--progressive-image-loading';
$theme_registry[$theme . '__progressive_image_loading']['path'] = drupal_get_path('module', 'progressive_image_loading') . '/templates';
$theme_registry['background_' . $theme . '__progressive_image_loading'] = $theme_registry[$theme];
$theme_registry['background_' . $theme . '__progressive_image_loading']['template'] = str_replace('_', '-', 'background-' . $theme) . '--progressive-image-loading';
$theme_registry['background_' . $theme . '__progressive_image_loading']['path'] = drupal_get_path('module', 'progressive_image_loading') . '/templates';
}
}
