365 lines
13 KiB
Plaintext
365 lines
13 KiB
Plaintext
<?php
|
|
|
|
/**
|
|
* @file
|
|
* Picture display formatter for image fields.
|
|
*/
|
|
|
|
use Drupal\picture\Entity\PictureMapping;
|
|
use \Drupal\Core\Template\Attribute;
|
|
|
|
/**
|
|
* Implements hook_help().
|
|
*/
|
|
function picture_help($path, $arg) {
|
|
$output = '';
|
|
switch ($path) {
|
|
case 'admin/help#picture':
|
|
$output .= '<h3>' . t('About') . '</h3>';
|
|
$output .= '<p>' . t('The Picture module provides an image formatter and breakpoint mappings to output responsive images using the HTML5 picture tag. For more information, see the <a href="!picture">online documentation for the Picture module</a>.', array( '!picture' => 'https://drupal.org/documentation/modules/picture')) . '</p>';
|
|
$output .= '<h3>' . t('Uses') . '</h3>';
|
|
$output .= '<dl>';
|
|
$output .= '<dt>' . t('Defining picture mappings') . '</dt>';
|
|
$output .= '<dd>' . t('By creating picture mappings you define the image styles that are being used to output images at certain breakpoints. On the <a href="!picture_mapping">Picture mappings</a> page, click <em>Add picture mapping</em> to create a new mapping. First chose a label and a breakpoint group and click Save. After that you can choose the image styles that will be used for each breakpoint. Image styles can be defined on the <a href="!image_styles">Image styles page</a> that is provided by the <a href="!image_help">Image module</a>. Breakpoints are defined in the configuration files of the theme. See the <a href="!breakpoint_help">help page of the Breakpoint module</a> for more information.', array('!picture_mapping' => \Drupal::url('picture.mapping_page'), '!image_styles' => \Drupal::url('image.style_list'),'!image_help' => \Drupal::url('help.page', array('name' => 'image')), '!breakpoint_help' => \Drupal::url('help.page', array('name' => 'breakpoint')))) . '</dd>';
|
|
$output .= '<dt>' . t('Using picture mappings in image fields') . '</dt>';
|
|
$output .= '<dd>' . t('After defining picture mappings, you can use them in the display settings for your image fields, so that the site displays responsive images using the HTML5 picture tag. Open the Manage display page for the entity type (content type, taxonomy vocabulary, etc.) that the Image field is attached to. Choose the format <em>Picture</em>, click the Edit icon and select one of the picture mappings that you have created. For general information on how to manage fields and their display see the <a href="!field_ui">help page of the Field UI module</a>. For information about entities see the <a href="!entity_help">help page of the Entity module</a>.', array('!field_ui' => \Drupal::url('help.page', array('name' => 'field_ui')),'!entity_help' => \Drupal::url('help.page', array('name' => 'entity')))) . '</dd>';
|
|
$output .= '</dl>';
|
|
break;
|
|
case 'admin/config/media/picturemapping':
|
|
$output .= '<p>' . t('A picture mapping associates an image style with each breakpoint defined by your theme.') . '</p>';
|
|
break;
|
|
|
|
}
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Implements hook_permission().
|
|
*/
|
|
function picture_permission() {
|
|
return array(
|
|
'administer pictures' => array(
|
|
'title' => t('Administer Pictures'),
|
|
'description' => t('Administer Pictures'),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Implements hook_menu().
|
|
*/
|
|
function picture_menu() {
|
|
$items = array();
|
|
|
|
$items['admin/config/media/picturemapping'] = array(
|
|
'title' => 'Picture Mappings',
|
|
'description' => 'Manage picture mappings',
|
|
'weight' => 10,
|
|
'route_name' => 'picture.mapping_page',
|
|
);
|
|
$items['admin/config/media/picturemapping/%picture_mapping'] = array(
|
|
'title' => 'Edit picture mapping',
|
|
'route_name' => 'picture.mapping_page_edit',
|
|
);
|
|
$items['admin/config/media/picturemapping/%picture_mapping/duplicate'] = array(
|
|
'title' => 'Duplicate picture mapping',
|
|
'route_name' => 'picture.mapping_page_duplicate',
|
|
);
|
|
|
|
return $items;
|
|
}
|
|
|
|
/**
|
|
* Implements hook_menu_link_defaults().
|
|
*/
|
|
function picture_menu_link_defaults() {
|
|
$links['picture.admin.config.picturemapping'] = array(
|
|
'link_title' => 'Picture Mappings',
|
|
'description' => 'Manage picture mappings',
|
|
'weight' => 10,
|
|
'route_name' => 'picture.mapping_page',
|
|
'parent' => 'system.admin.config.media',
|
|
);
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Load one picture by its identifier.
|
|
*
|
|
* @param int $id
|
|
* The id of the picture mapping to load.
|
|
*
|
|
* @return \Drupal\picture\Picture
|
|
* The entity object, or NULL if there is no entity with the given id.
|
|
*
|
|
* @todo Needed for menu_callback
|
|
*
|
|
* @see http://drupal.org/node/1798214
|
|
*
|
|
*/
|
|
function picture_mapping_load($id) {
|
|
return entity_load('picture_mapping', $id);
|
|
}
|
|
|
|
/**
|
|
* Implements hook_theme().
|
|
*/
|
|
function picture_theme() {
|
|
return array(
|
|
'picture' => array(
|
|
'variables' => array(
|
|
'style_name' => NULL,
|
|
'uri' => NULL,
|
|
'width' => NULL,
|
|
'height' => NULL,
|
|
'alt' => '',
|
|
'title' => NULL,
|
|
'attributes' => array(),
|
|
'breakpoints' => array(),
|
|
),
|
|
),
|
|
'picture_formatter' => array(
|
|
'variables' => array(
|
|
'item' => NULL,
|
|
'path' => NULL,
|
|
'image_style' => NULL,
|
|
'breakpoints' => array(),
|
|
),
|
|
),
|
|
'picture_source' => array(
|
|
'variables' => array(
|
|
'src' => NULL,
|
|
'srcset' => NULL,
|
|
'dimensions' => NULL,
|
|
'media' => NULL,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns HTML for a picture field formatter.
|
|
*
|
|
* @param array $variables
|
|
* An associative array containing:
|
|
* - item: An ImageItem object.
|
|
* - image_style: An optional image style.
|
|
* - path: An optional array containing the link 'path' and link 'options'.
|
|
* - breakpoints: An array containing breakpoints.
|
|
*
|
|
* @ingroup themeable
|
|
*/
|
|
function theme_picture_formatter($variables) {
|
|
$item = $variables['item'];
|
|
if (!isset($variables['breakpoints']) || empty($variables['breakpoints'])) {
|
|
$image_formatter = array(
|
|
'#theme' => 'image_formatter',
|
|
'#item' => $item,
|
|
'#image_style' => $variables['image_style'],
|
|
'#path' => $variables['path'],
|
|
);
|
|
return drupal_render($image_formatter);
|
|
}
|
|
|
|
$picture = array(
|
|
'#theme' => 'picture',
|
|
'#width' => $item->width,
|
|
'#height' => $item->height,
|
|
'#style_name' => $variables['image_style'],
|
|
'#breakpoints' => $variables['breakpoints'],
|
|
);
|
|
if (isset($item->uri)) {
|
|
$picture['#uri'] = $item->uri;
|
|
}
|
|
elseif ($entity = $item->entity) {
|
|
$picture['#uri'] = $entity->getFileUri();
|
|
$picture['#entity'] = $entity;
|
|
}
|
|
$picture['#alt'] = $item->alt;
|
|
if (drupal_strlen($item->title) != 0) {
|
|
$picture['#title'] = $item->title;
|
|
}
|
|
// @todo Add support for route names.
|
|
if (isset($variables['path']['path'])) {
|
|
$path = $variables['path']['path'];
|
|
$options = isset($variables['path']['options']) ? $variables['path']['options'] : array();
|
|
$options['html'] = TRUE;
|
|
return l($picture, $path, $options);
|
|
}
|
|
|
|
return drupal_render($picture);
|
|
}
|
|
|
|
/**
|
|
* Returns HTML for a picture.
|
|
*
|
|
* @param $variables
|
|
* An associative array containing:
|
|
* - uri: Either the path of the image file (relative to base_path()) or a
|
|
* full URL.
|
|
* - width: The width of the image (if known).
|
|
* - height: The height of the image (if known).
|
|
* - alt: The alternative text for text-based browsers.
|
|
* - breakpoints: An array containing breakpoints.
|
|
*
|
|
* @ingroup themeable
|
|
*/
|
|
function theme_picture($variables) {
|
|
// Make sure that width and height are proper values
|
|
// If they exists we'll output them
|
|
// @see http://www.w3.org/community/respimg/2012/06/18/florians-compromise/
|
|
if (isset($variables['width']) && empty($variables['width'])) {
|
|
unset($variables['width']);
|
|
unset($variables['height']);
|
|
}
|
|
elseif (isset($variables['height']) && empty($variables['height'])) {
|
|
unset($variables['width']);
|
|
unset($variables['height']);
|
|
}
|
|
|
|
$sources = array();
|
|
$output = array();
|
|
|
|
// Fallback image, output as source with media query.
|
|
$sources[] = array(
|
|
'src' => entity_load('image_style', $variables['style_name'])->buildUrl($variables['uri']),
|
|
'dimensions' => picture_get_image_dimensions($variables),
|
|
);
|
|
|
|
// All breakpoints and multipliers.
|
|
foreach ($variables['breakpoints'] as $breakpoint_name => $multipliers) {
|
|
$breakpoint = breakpoint_load($breakpoint_name);
|
|
if ($breakpoint) {
|
|
$new_sources = array();
|
|
foreach ($multipliers as $multiplier => $image_style) {
|
|
$new_source = $variables;
|
|
$new_source['style_name'] = $image_style;
|
|
$new_source['#multiplier'] = $multiplier;
|
|
$new_sources[] = $new_source;
|
|
}
|
|
|
|
// Only one image, use src.
|
|
if (count($new_sources) == 1) {
|
|
$sources[] = array(
|
|
'src' => entity_load('image_style', $new_sources[0]['style_name'])->buildUrl($new_sources[0]['uri']),
|
|
'dimensions' => picture_get_image_dimensions($new_sources[0]),
|
|
'media' => $breakpoint->mediaQuery,
|
|
);
|
|
}
|
|
else {
|
|
// Multiple images, use srcset.
|
|
$srcset = array();
|
|
foreach ($new_sources as $new_source) {
|
|
$srcset[] = entity_load('image_style', $new_source['style_name'])->buildUrl($new_source['uri']) . ' ' . $new_source['#multiplier'];
|
|
}
|
|
$sources[] = array(
|
|
'srcset' => implode(', ', $srcset),
|
|
'dimensions' => picture_get_image_dimensions($new_sources[0]),
|
|
'media' => $breakpoint->mediaQuery,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($sources)) {
|
|
$attributes = array();
|
|
foreach (array('alt', 'title') as $key) {
|
|
if (isset($variables[$key])) {
|
|
$attributes[$key] = $variables[$key];
|
|
}
|
|
}
|
|
$output[] = '<picture' . new Attribute($attributes) . '>';
|
|
|
|
// Add source tags to the output.
|
|
foreach ($sources as $source) {
|
|
$picture_source = array(
|
|
'#theme' => 'picture_source',
|
|
'#src' => $source['src'],
|
|
'#dimensions' => $source['dimensions'],
|
|
);
|
|
if (isset($source['media'])) {
|
|
$picture_source['#media'] = $source['media'];
|
|
}
|
|
if (isset($source['srcset'])) {
|
|
$picture_source['#srcset'] = $source['srcset'];
|
|
}
|
|
$output[] = drupal_render($picture_source);
|
|
}
|
|
|
|
// Output the fallback image.
|
|
$image_style = array(
|
|
'#theme' => 'image_style',
|
|
'#style_name' => $variables['style_name'],
|
|
'#width' => $variables['width'],
|
|
'#height' => $variables['height'],
|
|
);
|
|
foreach (array('uri', 'alt', 'title', 'attributes') as $key) {
|
|
if (isset($variables[$key])) {
|
|
$image_style["#$key"] = $variables[$key];
|
|
}
|
|
}
|
|
$output[] = ' <noscript>' . drupal_render($image_style) . '</noscript>';
|
|
$output[] = '</picture>';
|
|
return implode("\n", $output);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns HTML for a source tag.
|
|
*
|
|
* @param type $variables
|
|
* An associative array containing:
|
|
* - media: The media query to use.
|
|
* - srcset: The srcset containing the the path of the image file or a full
|
|
* URL and optionally multipliers.
|
|
* - src: Either the path of the image file (relative to base_path()) or a
|
|
* full URL.
|
|
* - dimensions: The width and height of the image (if known).
|
|
*
|
|
* @ingroup themeable
|
|
*/
|
|
function theme_picture_source($variables) {
|
|
$output = array();
|
|
if (isset($variables['media']) && !empty($variables['media'])) {
|
|
if (!isset($variables['srcset'])) {
|
|
$output[] = '<!-- <source media="' . $variables['media'] . '" src="' . $variables['src'] . '" ' . new Attribute($variables['dimensions']) . ' /> -->';
|
|
$output[] = '<source media="' . $variables['media'] . '" src="' . $variables['src'] . '" ' . new Attribute($variables['dimensions']) . '/>';
|
|
}
|
|
elseif (!isset($variables['src'])) {
|
|
$output[] = '<!-- <source media="' . $variables['media'] . '" srcset="' . $variables['srcset'] . '" ' . new Attribute($variables['dimensions']) . ' /> -->';
|
|
$output[] = '<source media="' . $variables['media'] . '" srcset="' . $variables['srcset'] . '" ' . new Attribute($variables['dimensions']) . ' />';
|
|
}
|
|
}
|
|
else {
|
|
$output[] = '<!-- <source src="' . $variables['src'] . '" ' . new Attribute($variables['dimensions']) . ' /> -->';
|
|
$output[] = '<source src="' . $variables['src'] . '" ' . new Attribute($variables['dimensions']) . '/>';
|
|
}
|
|
return implode("\n", $output);
|
|
}
|
|
|
|
/**
|
|
* Determines the dimensions of an image.
|
|
*
|
|
* @param $variables
|
|
* An associative array containing:
|
|
* - style_name: The name of the style to be used to alter the original image.
|
|
* - width: The width of the source image (if known).
|
|
* - height: The height of the source image (if known).
|
|
*
|
|
* @return array
|
|
* Dimensions to be modified - an array with components width and height, in
|
|
* pixels.
|
|
*/
|
|
function picture_get_image_dimensions($variables) {
|
|
// Determine the dimensions of the styled image.
|
|
$dimensions = array(
|
|
'width' => $variables['width'],
|
|
'height' => $variables['height'],
|
|
);
|
|
|
|
entity_load('image_style', $variables['style_name'])->transformDimensions($dimensions);
|
|
|
|
return $dimensions;
|
|
}
|