View source
<?php
namespace Drupal\blazy;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Security\TrustedCallbackInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Cache\Cache;
class BlazyManager extends BlazyManagerBase implements TrustedCallbackInterface {
public static function trustedCallbacks() {
return [
'preRenderBlazy',
'preRenderBuild',
];
}
public function getBlazy(array $build = []) {
foreach (BlazyDefault::themeProperties() as $key) {
$build[$key] = isset($build[$key]) ? $build[$key] : [];
}
$settings =& $build['settings'];
$settings += BlazyDefault::itemSettings();
$settings['uri'] = $uri = $settings['uri'] ?: Blazy::uri($build['item']);
$settings['_valid'] = BlazyUtil::isValidUri($uri);
$settings['_missing'] = $settings['_valid'] && !is_file($uri);
$content = empty($uri) || $settings['_missing'] ? $build['content'] : [
'#theme' => 'blazy',
'#delta' => $settings['delta'],
'#item' => $build['item'],
'#image_style' => $settings['image_style'],
'#build' => $build,
'#pre_render' => [
[
$this,
'preRenderBlazy',
],
],
];
$this->moduleHandler
->alter('blazy', $content, $settings);
return $content;
}
public function preRenderBlazy(array $element) {
$build = $element['#build'];
unset($element['#build']);
$this
->prepareBlazy($element, $build);
$settings = $element['#settings'];
if (!empty($settings['media_switch'])) {
if ($settings['media_switch'] == 'content' && !empty($settings['content_url'])) {
$element['#url'] = $settings['content_url'];
}
elseif (!empty($settings['lightbox'])) {
BlazyLightbox::build($element);
}
}
return $element;
}
protected function prepareBlazy(array &$element, array $build) {
$item = $build['item'];
$settings =& $build['settings'];
$settings['_api'] = TRUE;
$pathinfo = pathinfo($settings['uri']);
$settings['extension'] = isset($pathinfo['extension']) ? $pathinfo['extension'] : '';
$settings['unstyled'] = BlazyUtil::unstyled($settings);
$settings['_richbox'] = !empty($settings['colorbox']) || !empty($settings['_richbox']);
if ($settings['unstyled']) {
$images = [
'box',
'box_media',
'image',
'thumbnail',
'responsive_image',
];
foreach ($images as $image) {
$settings[$image . '_style'] = '';
}
}
foreach (BlazyDefault::themeAttributes() as $key) {
$key = $key . '_attributes';
$build[$key] = isset($build[$key]) ? $build[$key] : [];
}
$attributes =& $build['attributes'];
$this
->thumbnailAndPlaceholder($attributes, $settings);
Blazy::urlAndDimensions($settings, $item);
$this
->buildContent($element, $build);
if (empty($build['content'])) {
$this
->buildMedia($element, $build);
}
if (!empty($settings['blazy_data']['dimensions'])) {
$attributes['data-dimensions'] = Json::encode($settings['blazy_data']['dimensions']);
}
foreach ([
'caption',
'media',
'wrapper',
] as $key) {
$element["#{$key}" . '_attributes'] = empty($build[$key . '_attributes']) ? [] : BlazyUtil::sanitize($build[$key . '_attributes']);
}
if ($build['captions'] && ($captions = $this
->buildCaption($build['captions'], $settings))) {
$element['#captions'] = $captions;
$element['#caption_attributes']['class'][] = $settings['item_id'] . '__caption';
}
$element['#attributes'] = $attributes;
$element['#settings'] = $settings;
$element['#url_attributes'] = $build['url_attributes'];
foreach ([
'content',
'icon',
'overlay',
'preface',
'postscript',
] as $key) {
$element["#{$key}"] = empty($element["#{$key}"]) ? $build[$key] : NestedArray::mergeDeep($element["#{$key}"], $build[$key]);
}
}
protected function buildContent(array &$element, array &$build) {
$settings =& $build['settings'];
if (empty($build['content'])) {
return;
}
$settings = array_merge($settings, BlazyDefault::richSettings());
$rich = $settings['type'] == 'rich' && !empty($settings['_richbox']);
if ($rich && isset($build['content'][0]['#settings']) && ($blazy = $build['content'][0]['#settings'])) {
if (!empty($settings['_hires']) && $blazy
->get('lightbox')) {
$settings = array_merge($settings, $blazy
->storage());
$element['#lightbox_html'] = $build['content'];
$build['content'] = [];
}
}
}
private function buildMedia(array &$element, array &$build) {
$item = $build['item'];
$settings =& $build['settings'];
$attributes =& $build['attributes'];
$item_attributes = empty($build['item_attributes']) ? [] : BlazyUtil::sanitize($build['item_attributes']);
if ($item && isset($item->_attributes)) {
$item_attributes += $item->_attributes;
unset($item->_attributes);
}
if (!empty($settings['resimage']) && empty($settings['unstyled'])) {
$this
->buildResponsiveImage($element, $attributes, $settings);
}
if (empty($settings['responsive_image_style_id'])) {
$this
->buildImage($element, $attributes, $item_attributes, $settings);
}
$element['#item_attributes'] = $item_attributes;
if (!empty($settings['urls'])) {
$attributes['class'][] = 'b-bg media--background';
$attributes['data-backgrounds'] = Json::encode($settings['urls']);
if (!empty($settings['is_preview'])) {
Blazy::inlineStyle($attributes, 'background-image: url(' . $settings['image_url'] . ');');
}
}
if (!empty($settings['fx']) && empty($settings['unstyled'])) {
$blur = [
'#theme' => 'image',
'#uri' => $settings['placeholder_ui'] ?: $settings['placeholder'],
'#attributes' => [
'class' => [
'b-lazy',
'b-blur',
'b-blur--tmp',
],
'data-src' => $settings['placeholder_fx'],
'loading' => 'lazy',
],
];
if (!empty($settings['decode'])) {
$blur['#attributes']['decoding'] = 'async';
}
unset($settings['placeholder_fx']);
$element['#preface']['blur'] = $blur;
if (isset($settings['width']) && $settings['width'] > 980) {
$attributes['class'][] = 'media--fx-lg';
}
}
}
private function buildResponsiveImage(array &$element, array &$attributes, array &$settings) {
$settings['responsive_image_style_id'] = $settings['resimage']
->id();
$responsive_image = $this
->getResponsiveImageStyles($settings['resimage']);
$element['#cache']['tags'] = $responsive_image['caches'];
if (!empty($settings['background'])) {
$srcset = $dimensions = [];
foreach ($responsive_image['styles'] as $style) {
$styled = array_merge($settings, BlazyUtil::transformDimensions($style, $settings, FALSE));
$data = $this
->backgroundImage($styled, $style);
$srcset[$styled['width']] = $data;
$dimensions[$styled['width']] = $data['ratio'];
}
ksort($srcset);
ksort($dimensions);
$settings['urls'] = $srcset;
$settings['blazy_data']['dimensions'] = $dimensions;
$settings['padding_bottom'] = end($dimensions);
$settings['image_url'] = empty($settings['is_preview']) ? $settings['placeholder'] : $settings['image_url'];
Blazy::lazyAttributes($attributes, $settings);
}
}
private function buildImage(array &$element, array &$attributes, array &$item_attributes, array &$settings) {
if (!empty($settings['lazy']) && !empty($settings['background'])) {
$settings['urls'][$settings['width']] = $this
->backgroundImage($settings);
$settings['image_url'] = empty($settings['is_preview']) ? $settings['placeholder'] : $settings['image_url'];
Blazy::lazyAttributes($attributes, $settings);
}
if (empty($settings['_no_cache'])) {
$file_tags = isset($settings['file_tags']) ? $settings['file_tags'] : [];
$settings['cache_tags'] = empty($settings['cache_tags']) ? $file_tags : Cache::mergeTags($settings['cache_tags'], $file_tags);
$element['#cache']['max-age'] = -1;
foreach ([
'contexts',
'keys',
'tags',
] as $key) {
if (!empty($settings['cache_' . $key])) {
$element['#cache'][$key] = $settings['cache_' . $key];
}
}
}
}
private function backgroundImage(array $settings, $style = NULL) {
return [
'src' => $style ? BlazyUtil::transformRelative($settings['uri'], $style) : $settings['image_url'],
'ratio' => round($settings['height'] / $settings['width'] * 100, 2),
];
}
public function buildCaption(array $captions, array $settings) {
$content = [];
foreach ($captions as $key => $caption_content) {
if ($caption_content) {
$content[$key]['content'] = $caption_content;
$content[$key]['tag'] = strpos($key, 'title') !== FALSE ? 'h2' : 'div';
$class = $key == 'alt' ? 'description' : str_replace('field_', '', $key);
$content[$key]['attributes'] = new Attribute();
$content[$key]['attributes']
->addClass($settings['item_id'] . '__caption--' . str_replace('_', '-', $class));
}
}
return $content ? [
'inline' => $content,
] : [];
}
protected function thumbnailAndPlaceholder(array &$attributes, array &$settings) {
$settings['placeholder_ui'] = $settings['placeholder'];
$path = $style = '';
if (!empty($settings['thumbnail_style'])) {
$style = $this
->entityLoad($settings['thumbnail_style'], 'image_style');
if ($style) {
$path = $style
->buildUri($settings['uri']);
$attributes['data-thumb'] = $settings['thumbnail_url'] = BlazyUtil::transformRelative($settings['uri'], $style);
if (!is_file($path) && BlazyUtil::isValidUri($path)) {
$style
->createDerivative($settings['uri'], $path);
}
}
}
if (!empty($settings['thumbnail_uri'])) {
$path = $settings['thumbnail_uri'];
$attributes['data-thumb'] = $settings['thumbnail_url'] = BlazyUtil::transformRelative($path);
}
if (!empty($settings['fx'])) {
$attributes['class'][] = 'media--fx';
if (empty($settings['placeholder_fx']) && empty($settings['unstyled'])) {
$this
->createPlaceholder($settings, $style, $path);
}
$attributes['data-animation'] = $settings['fx'];
}
if (empty($settings['image_style']) && !empty($settings['resimage'])) {
$fallback = $settings['resimage']
->getFallbackImageStyle();
if ($fallback == '_empty image_') {
$placeholder = empty($settings['width']) ? BlazyInterface::PLACEHOLDER : BlazyUtil::generatePlaceholder($settings['width'], $settings['height']);
$settings['image_url'] = empty($settings['placeholder']) ? $placeholder : $settings['placeholder'];
}
else {
$settings['image_style'] = $fallback;
}
}
}
protected function createPlaceholder(array &$settings, $style = NULL, $path = '') {
if (empty($path) && ($style = $this
->entityLoad('thumbnail', 'image_style')) && BlazyUtil::isValidUri($settings['uri'])) {
$path = $style
->buildUri($settings['uri']);
}
if ($path && BlazyUtil::isValidUri($path)) {
if (!is_file($path) && $style) {
$style
->createDerivative($settings['uri'], $path);
}
if (is_file($path)) {
$settings['placeholder_fx'] = 'data:image/' . pathinfo($path, PATHINFO_EXTENSION) . ';base64,' . base64_encode(file_get_contents($path));
$settings['use_loading'] = FALSE;
}
}
}
public function build(array $build = []) {
$settings =& $build['settings'];
$settings['_grid'] = isset($settings['_grid']) ? $settings['_grid'] : !empty($settings['style']) && !empty($settings['grid']);
if (empty($settings['_grid'])) {
$settings = $this
->getSettings($build);
$this
->prepareBuild($build);
$build['#blazy'] = $settings;
$this
->setAttachments($build, $settings);
}
else {
$content = [
'#build' => $build,
'#pre_render' => [
[
$this,
'preRenderBuild',
],
],
];
$build = empty($settings['use_field']) ? $content : [
$content,
];
}
$this->moduleHandler
->alter('blazy_build', $build, $settings);
return $build;
}
public function preRenderBuild(array $element) {
$build = $element['#build'];
unset($element['#build']);
$attributes = isset($element['#attributes']) ? $element['#attributes'] : [];
$attributes = isset($element['#theme_wrappers'], $element['#theme_wrappers']['container']['#attributes']) ? $element['#theme_wrappers']['container']['#attributes'] : $attributes;
$settings = $this
->getSettings($build);
$this
->prepareBuild($build);
$element = BlazyGrid::build($build, $settings);
$this
->setAttachments($element, $settings);
if ($attributes) {
if (isset($element['#ajax_replace_class'])) {
$element['#container_attributes'] = $attributes;
}
else {
$element['#attributes'] = NestedArray::mergeDeep($element['#attributes'], $attributes);
}
}
return $element;
}
protected function getSettings(array &$build) {
$settings = isset($build['settings']) ? $build['settings'] : [];
$settings += BlazyDefault::htmlSettings();
if (!empty($settings['first_image']) && !empty($settings['check_blazy'])) {
if (is_array($settings['first_image'])) {
$this
->isBlazy($settings, $settings['first_image']);
}
}
return $settings;
}
protected function prepareBuild(array &$build) {
$build = isset($build['items']) ? $build['items'] : $build;
unset($build['items'], $build['settings']);
}
public function getImage(array $build = []) {
@trigger_error('getImage is deprecated in blazy:8.x-2.0 and is removed from blazy:8.x-3.0. Use \\Drupal\\blazy\\BlazyManager::getBlazy() instead. See https://www.drupal.org/node/3103018', E_USER_DEPRECATED);
return $this
->getBlazy($build);
}
}