View source
<?php
namespace Drupal\blazy;
use Drupal\blazy\Utility\NestedArray;
class Blazy {
const PLACEHOLDER = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
private static $blazyId;
public static function container($content, $attributes, $tag = 'div') {
$build = array_filter($content);
if ($build || $attributes) {
$build['#prefix'] = '<' . $tag . drupal_attributes($attributes) . '>';
$build['#suffix'] = '</' . $tag . '>';
}
return $build;
}
public static function urlAndDimensions(array &$settings, $item = NULL) {
self::imageDimensions($settings, $item);
self::imageUrl($settings, $item);
}
public static function imageDimensions(array &$settings, $item = NULL, $initial = FALSE) {
$width = $initial ? '_width' : 'width';
$height = $initial ? '_height' : 'height';
if (empty($settings[$width])) {
$settings[$width] = $item && isset($item->width) ? $item->width : NULL;
$settings[$height] = $item && isset($item->height) ? $item->height : NULL;
}
}
public static function imageUrl(array &$settings, $item = NULL) {
$uri = $settings['uri'];
if ($settings['image_style']) {
$settings['image_url'] = image_style_url($settings['image_style'], $uri);
if (empty($settings['_dimensions'])) {
$settings = array_merge($settings, self::transformDimensions($settings['image_style'], $item));
}
}
else {
$image_url = file_valid_uri($uri) ? file_create_url($uri) : $uri;
$settings['image_url'] = $settings['image_url'] ?: $image_url;
}
$data_uri = !empty($settings['use_data_uri']) && substr($settings['image_url'], 0, 10) === 'data:image';
if (!empty($settings['_check_protocol']) && !$data_uri) {
$settings['image_url'] = drupal_strip_dangerous_protocols($settings['image_url']);
}
}
public static function transformDimensions($image_style, $item = NULL) {
$dimensions['width'] = $item && isset($item->width) ? $item->width : NULL;
$dimensions['height'] = $item && isset($item->height) ? $item->height : NULL;
image_style_transform_dimensions($image_style, $dimensions);
return $dimensions;
}
public static function buildUri($image_url) {
if (!url_is_external($image_url) && ($path = drupal_parse_url($image_url)['path'])) {
$normal_path = drupal_get_normal_path($path);
$public_path = variable_get('file_public_path', 'sites/default/files');
if ($public_path && strpos($normal_path, $public_path) !== FALSE) {
$rel_path = str_replace($public_path, '', $normal_path);
return file_build_uri($rel_path);
}
}
return FALSE;
}
public static function imageAttributes(array &$attributes, array $settings, $item = NULL) {
$attributes['typeof'] = [
'foaf:Image',
];
if ($item && isset($item->_attributes)) {
$attributes += $item->_attributes;
unset($item->_attributes);
}
if ($settings['width'] && !isset($attributes['width'])) {
$attributes['height'] = $settings['height'];
$attributes['width'] = $settings['width'];
}
if ($item) {
foreach ([
'width',
'height',
'alt',
'title',
] as $key) {
if (isset($item->{$key})) {
if (array_key_exists($key, $attributes)) {
continue;
}
if ($key == 'title' && strlen($item->title) != 0) {
$attributes['title'] = $item->title;
}
elseif (!isset($attributes[$key])) {
$attributes[$key] = $item->{$key};
}
}
}
}
}
public static function lazyAttributes(array &$attributes, array $settings = []) {
$attributes['class'][] = $settings['lazy_class'];
$attributes['data-' . $settings['lazy_attribute']] = $settings['image_url'];
$attributes['loading'] = 'lazy';
}
public static function aspectRatioAttributes(array &$attributes, array &$settings) {
$attributes['class'][] = 'media--ratio media--ratio--' . $settings['ratio'];
if ($settings['width'] && in_array($settings['ratio'], [
'enforced',
'fluid',
])) {
$padding = $settings['padding_bottom'] ?: round($settings['height'] / $settings['width'] * 100, 2);
self::inlineStyle($attributes, 'padding-bottom: ' . $padding . '%;');
$settings['_breakpoint_ratio'] = $settings['ratio'];
$attributes['data-ratio'] = $padding;
}
}
public static function containerAttributes(array &$variables, array $settings = []) {
$settings += [
'namespace' => 'blazy',
];
$is_vars = isset($variables['classes_array']);
$classes = $is_vars ? $variables['classes_array'] : (empty($variables['class']) ? [] : $variables['class']);
$attrs['data-blazy'] = empty($settings['blazy_data']) ? '' : drupal_json_encode($settings['blazy_data']);
if (!empty($settings['media_switch']) && $settings['media_switch'] != 'content') {
$switch = str_replace('_', '-', $settings['media_switch']);
$attrs['data-' . $switch . '-gallery'] = '';
$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;
}
}
}
if ($is_vars) {
$variables['attributes_array'] = isset($variables['attributes_array']) ? NestedArray::mergeDeep($variables['attributes_array'], $attrs) : $attrs;
}
else {
$variables = NestedArray::mergeDeep($variables, $attrs);
}
$variables[$is_vars ? 'classes_array' : 'class'] = array_merge([
'blazy',
], $classes);
}
public static function sanitize(array $attributes = []) {
$clean_attributes = [];
$tags = [
'href',
'poster',
'src',
'about',
'data',
'action',
'formaction',
];
foreach ($attributes as $key => $value) {
if (is_array($value)) {
$value = implode(' ', $value);
$clean_attributes[$key] = array_map('drupal_clean_css_identifier', explode(' ', $value));
}
else {
$kid = substr($key, 0, 2) === 'on' || in_array($key, $tags);
$key = $kid ? 'data-' . $key : $key;
$clean_attributes[$key] = $kid ? drupal_clean_css_identifier($value) : check_plain($value);
}
}
return $clean_attributes;
}
public static function getHtmlId($string = 'blazy', $id = '') {
if (!isset(static::$blazyId)) {
static::$blazyId = 0;
}
$id = empty($id) ? $string . '-' . ++static::$blazyId : $id;
return trim(str_replace('_', '-', strip_tags($id)));
}
public static function inlineStyle(array &$attributes, $css) {
$attributes['style'] = (isset($attributes['style']) ? $attributes['style'] : '') . $css;
}
public static function widthFromDescriptors($descriptor = '') {
if (empty($descriptor)) {
return FALSE;
}
$descriptor = trim($descriptor);
if (is_numeric($descriptor)) {
return (int) $descriptor;
}
$width = strpos($descriptor, "w") !== FALSE ? str_replace('w', '', $descriptor) : $descriptor;
if (strpos($descriptor, " ") !== FALSE) {
list($width, $px) = array_pad(array_map('trim', explode(" ", $width, 2)), 2, NULL);
if (is_numeric($px) && strpos($width, "x") !== FALSE) {
$width = $px;
}
}
return is_numeric($width) ? (int) $width : FALSE;
}
public static function buildBreakpointAttributes(array &$attributes, array &$settings, $item = NULL) {
if (empty($settings['breakpoints'])) {
return;
}
$srcset = $json = $bg_sources = [];
foreach ($settings['breakpoints'] as $breakpoint) {
$url = image_style_url($breakpoint['image_style'], $settings['uri']);
$width = self::widthFromDescriptors($breakpoint['width']);
if (!empty($settings['_breakpoint_ratio']) && empty($settings['blazy_data']['dimensions'])) {
$dim = self::transformDimensions($breakpoint['image_style'], $item);
if ($width) {
$ratio = round($dim['height'] / $dim['width'] * 100, 2);
$json[$width] = $ratio;
}
}
else {
$ratio = $settings['blazy_data']['dimensions'][$width];
}
if ($settings['background']) {
$bg_sources[$width] = [
'src' => $url,
'ratio' => $ratio,
];
}
else {
$width = is_numeric($width) ? $width . 'w' : $width;
$srcset[] = $url . ' ' . $width;
}
}
if ($srcset) {
$settings['srcset'] = implode(', ', $srcset);
$attributes['srcset'] = '';
$attributes['data-srcset'] = $settings['srcset'];
$attributes['sizes'] = '100w';
if (!empty($settings['sizes'])) {
$attributes['sizes'] = trim($settings['sizes']);
unset($attributes['height'], $attributes['width']);
}
}
if ($json) {
$settings['blazy_data']['dimensions'] = $json;
}
if ($bg_sources) {
ksort($bg_sources);
$settings['urls'] = $bg_sources;
}
}
}