View source
<?php
namespace Drupal\blazy;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Template\Attribute;
class Blazy implements BlazyInterface {
use BlazyDeprecatedTrait;
private static $blazyId;
public static function preprocessBlazy(array &$variables) {
$element = $variables['element'];
foreach (BlazyDefault::themeProperties() as $key) {
$variables[$key] = isset($element["#{$key}"]) ? $element["#{$key}"] : [];
}
foreach (BlazyDefault::themeAttributes() as $key) {
$key = $key . '_attributes';
$variables[$key] = empty($element["#{$key}"]) ? [] : new Attribute($element["#{$key}"]);
}
$settings =& $variables['settings'];
$settings += BlazyDefault::itemSettings();
if (empty($settings['uri'])) {
return;
}
if (empty($settings['_api'])) {
self::urlAndDimensions($settings, $variables['item']);
}
if (empty($variables['content'])) {
self::buildMedia($variables);
}
$settings['ratio'] = empty($settings['width']) ? '' : $settings['ratio'];
if ($settings['ratio']) {
self::aspectRatioAttributes($variables['attributes'], $settings);
}
$attributes =& $variables['attributes'];
$classes = empty($attributes['class']) ? [] : $attributes['class'];
$attributes['class'] = array_merge([
'media',
'media--blazy',
], $classes);
}
public static function buildMedia(array &$variables) {
$settings = $variables['settings'];
if (empty($settings['background'])) {
if (!empty($settings['responsive_image_style_id'])) {
self::buildResponsiveImage($variables);
}
else {
self::buildImage($variables);
}
}
if ($settings['use_media'] && empty($settings['_noiframe'])) {
self::buildIframe($variables);
}
if ($variables['image']) {
self::imageAttributes($variables);
}
}
public static function urlAndDimensions(array &$settings, $item = NULL) {
BlazyUtil::imageDimensions($settings, $item);
BlazyUtil::imageUrl($settings);
$is_media = in_array($settings['type'], [
'audio',
'video',
]);
$settings['placeholder'] = empty($settings['placeholder']) ? BlazyUtil::generatePlaceholder($settings['width'], $settings['height']) : $settings['placeholder'];
$settings['use_media'] = $settings['embed_url'] && $is_media;
$settings['use_loading'] = empty($settings['is_preview']) ? $settings['use_loading'] : FALSE;
}
public static function buildResponsiveImage(array &$variables) {
$settings = $variables['settings'];
$attributes = empty($settings['is_preview']) ? [
'data-b-lazy' => $settings['one_pixel'],
'data-placeholder' => $settings['placeholder'],
] : [];
$variables['image'] += [
'#type' => 'responsive_image',
'#responsive_image_style_id' => $settings['responsive_image_style_id'],
'#uri' => $settings['uri'],
'#attributes' => $attributes,
];
}
public static function buildImage(array &$variables) {
$settings = $variables['settings'];
$variables['image'] += [
'#theme' => 'image',
'#uri' => !empty($settings['is_preview']) || empty($settings['lazy']) ? $settings['image_url'] : $settings['placeholder'],
];
}
public static function imageAttributes(array &$variables) {
$item = $variables['item'];
$settings =& $variables['settings'];
$image =& $variables['image'];
$attributes =& $variables['item_attributes'];
if ($item) {
if (!isset($attributes['alt'])) {
$attributes['alt'] = empty($item->alt) ? NULL : trim($item->alt);
}
if (isset($item->title) && mb_strlen($item->title) != 0) {
$attributes['title'] = trim($item->title);
}
}
if (!isset($attributes['width']) && empty($settings['unstyled'])) {
$image['#height'] = $settings['height'];
$image['#width'] = $settings['width'];
}
$attributes['class'][] = 'media__image';
if (!empty($settings['decode'])) {
$attributes['decoding'] = 'async';
}
self::commonAttributes($attributes, $variables['settings']);
$image['#attributes'] = empty($image['#attributes']) ? $attributes : NestedArray::mergeDeep($image['#attributes'], $attributes);
if (!empty($settings['noscript']) && empty($settings['is_preview'])) {
self::buildNoscriptImage($variables);
}
if (!empty($settings['lazy'])) {
self::lazyAttributes($image['#attributes'], $settings);
}
}
public static function iframeAttributes(array &$settings) {
if (empty($settings['is_preview'])) {
$attributes['data-src'] = $settings['embed_url'];
$attributes['src'] = 'about:blank';
$attributes['class'][] = 'b-lazy';
$attributes['allowfullscreen'] = TRUE;
$attributes['loading'] = 'lazy';
}
else {
$attributes['src'] = $settings['embed_url'];
$attributes['sandbox'] = TRUE;
}
$attributes['class'][] = 'media__iframe';
self::commonAttributes($attributes, $settings);
return $attributes;
}
public static function buildIframe(array &$variables) {
$settings =& $variables['settings'];
$settings['player'] = empty($settings['lightbox']) && $settings['media_switch'] == 'media';
if (empty($variables['url'])) {
$variables['image'] = empty($settings['media_switch']) ? [] : $variables['image'];
$variables['iframe'] = [
'#type' => 'html_tag',
'#tag' => 'iframe',
'#attributes' => self::iframeAttributes($settings),
];
$variables['attributes']['data-media'] = Json::encode([
'type' => $settings['type'],
]);
}
}
public static function buildNoscriptImage(array &$variables) {
$settings = $variables['settings'];
$noscript = $variables['image'];
$noscript['#uri'] = empty($settings['responsive_image_style_id']) ? $settings['image_url'] : $settings['uri'];
$noscript['#attributes']['data-b-noscript'] = TRUE;
$variables['noscript'] = [
'#type' => 'inline_template',
'#template' => '{{ prefix | raw }}{{ noscript }}{{ suffix | raw }}',
'#context' => [
'noscript' => $noscript,
'prefix' => '<noscript>',
'suffix' => '</noscript>',
],
];
}
public static function lazyAttributes(array &$attributes, array $settings = []) {
if (empty($settings['is_preview'])) {
$attributes['class'][] = $settings['lazy_class'];
$attributes['data-' . $settings['lazy_attribute']] = $settings['image_url'];
}
}
public static function commonAttributes(array &$attributes, array $settings = []) {
$attributes['class'][] = 'media__element';
}
public static function aspectRatioAttributes(array &$attributes, array &$settings) {
$settings['ratio'] = empty($settings['ratio']) ? '' : str_replace(':', '', $settings['ratio']);
if ($settings['height'] && $settings['ratio'] == 'fluid') {
$padding = $settings['padding_bottom'] ?: round($settings['height'] / $settings['width'] * 100, 2);
self::inlineStyle($attributes, 'padding-bottom: ' . $padding . '%;');
$attributes['data-ratio'] = $padding;
}
}
public static function containerAttributes(array &$attributes, array $settings = []) {
$settings += [
'namespace' => 'blazy',
];
$classes = empty($attributes['class']) ? [] : $attributes['class'];
$attributes['data-blazy'] = empty($settings['blazy_data']) ? '' : Json::encode($settings['blazy_data']);
if (!empty($settings['media_switch']) && $settings['media_switch'] != 'content') {
$switch = str_replace('_', '-', $settings['media_switch']);
$attributes['data-' . $switch . '-gallery'] = TRUE;
$classes[] = 'blazy--' . $switch;
}
foreach ([
'field',
'view',
] as $key) {
if (!empty($settings[$key . '_name'])) {
$name = str_replace('_', '-', $settings[$key . '_name']);
$name = $key == 'view' ? 'view--' . $name : $name;
$classes[] = $settings['namespace'] . '--' . $key;
$classes[] = $settings['namespace'] . '--' . $name;
if (!empty($settings['current_view_mode'])) {
$view_mode = str_replace('_', '-', $settings['current_view_mode']);
$classes[] = $settings['namespace'] . '--' . $name . '--' . $view_mode;
}
}
}
$attributes['class'] = array_merge([
'blazy',
], $classes);
}
public static function preprocessResponsiveImage(array &$variables) {
$image =& $variables['img_element'];
$attributes =& $variables['attributes'];
$placeholder = empty($attributes['data-placeholder']) ? static::PLACEHOLDER : $attributes['data-placeholder'];
if (!isset($attributes['data-b-noscript'])) {
if (!$variables['output_image_tag']) {
if (isset($variables['sources']) && is_array($variables['sources'])) {
foreach ($variables['sources'] as &$source) {
$source
->setAttribute('data-srcset', $source['srcset']
->value());
$source
->setAttribute('srcset', '');
}
}
$image['#uri'] = $placeholder;
$image['#srcset'] = '';
unset($attributes['data-srcset'], $image['#attributes']['data-srcset']);
}
else {
$image['#attributes']['data-srcset'] = $attributes['srcset']
->value();
$image['#attributes']['srcset'] = '';
}
if (!empty($attributes['data-b-lazy'])) {
$image['#uri'] = $placeholder;
}
$image['#attributes']['class'][] = 'b-responsive';
}
foreach ([
'placeholder',
'b-lazy',
'b-noscript',
] as $key) {
unset($attributes['data-' . $key], $image['#attributes']['data-' . $key]);
}
}
public static function preprocessFileVideo(array &$variables) {
if ($files = $variables['files']) {
if (empty($variables['attributes']['data-b-preview'])) {
$variables['attributes']
->addClass([
'b-lazy',
]);
foreach ($files as $file) {
$source_attributes =& $file['source_attributes'];
$source_attributes
->setAttribute('data-src', $source_attributes['src']
->value());
$source_attributes
->setAttribute('src', '');
}
}
if (isset($files[0], $files[0]['blazy']) && ($blazy = $files[0]['blazy'])) {
if ($blazy
->get('image') && $blazy
->get('uri')) {
$settings = $blazy
->storage();
$settings['_dimensions'] = TRUE;
BlazyUtil::imageUrl($settings);
if (!empty($settings['image_url'])) {
$variables['attributes']
->setAttribute('poster', $settings['image_url']);
}
if (!empty($settings['lightbox'])) {
$variables['attributes']
->setAttribute('autoplay', TRUE);
}
}
}
$attrs = [
'data-b-lazy',
'data-b-preview',
];
$variables['attributes']
->addClass([
'media__element',
]);
$variables['attributes']
->removeAttribute($attrs);
}
}
public static function preprocessField(array &$variables) {
$element =& $variables['element'];
$settings = empty($element['#blazy']) ? [] : $element['#blazy'];
if (!empty($element['#third_party_settings']['blazy']['blazy'])) {
BlazyAlter::thirdPartyPreprocessField($variables);
}
if (empty($settings['_grid'])) {
self::containerAttributes($variables['attributes'], $settings);
}
}
public static function getHtmlId($string = 'blazy', $id = '') {
if (!isset(static::$blazyId)) {
static::$blazyId = 0;
}
$id = empty($id) ? $string . '-' . ++static::$blazyId : $id;
return Html::getId($id);
}
public static function inlineStyle(array &$attributes, $css) {
$attributes['style'] = (isset($attributes['style']) ? $attributes['style'] : '') . $css;
}
public static function uri($item) {
$fallback = isset($item->uri) ? $item->uri : '';
return empty($item) ? '' : (($entity = $item->entity) && empty($item->uri) ? $entity
->getFileUri() : $fallback);
}
public static function image(array $attributes = []) {
$item = new \stdClass();
foreach ([
'uri',
'width',
'height',
'target_id',
'alt',
'title',
] as $key) {
if (isset($attributes[$key])) {
$item->{$key} = $attributes[$key];
}
}
return $item;
}
public static function streamWrapperManager() {
return \Drupal::hasService('stream_wrapper_manager') ? \Drupal::service('stream_wrapper_manager') : NULL;
}
public static function routeMatch() {
return \Drupal::routeMatch();
}
public static function isPreview() {
return in_array(self::routeMatch()
->getRouteName(), [
'entity_embed.preview',
'media.filter.preview',
]);
}
public static function configSchemaInfoAlter(array &$definitions, $formatter = 'blazy_base', array $settings = []) {
BlazyAlter::configSchemaInfoAlter($definitions, $formatter, $settings);
}
}