picture.module in Picture 7
Same filename and directory in other branches
Picture formatter.
File
picture.moduleView source
<?php
/**
* @file
* Picture formatter.
*/
define('PICTURE_CLASS', 'picture');
define('PICTURE_SEPARATOR', '__');
define('PICTURE_EMPTY_IMAGE', '_empty image_');
define('PICTURE_ORIGINAL_IMAGE', '_original image_');
define('PICTURE_IMPLEMENTATION_PICTUREFILL2', 'picturefill2');
define('PICTURE_IMPLEMENTATION_PICTUREFILL', 'picturefill');
define('PICTURE_IMPLEMENTATION_WEBLINC', 'weblinc');
define('PICTURE_IMPLEMENTATION_DEFAULT', 'picturefill');
if (!variable_get('picture_updated_to_file_entity_2', FALSE)) {
module_load_include('file_entity_1.inc', 'picture');
}
/**
* 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/picture'] = array(
'title' => 'Picture',
'description' => 'Manage Pictures',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'picture_admin_breakpoints',
),
'access arguments' => array(
'administer pictures',
),
'file' => 'picture.admin.inc',
);
$items['admin/config/media/picture/groups'] = array(
'title' => 'Groups',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 10,
);
$items['admin/config/media/picture/settings'] = array(
'title' => 'Settings',
'type' => MENU_LOCAL_TASK,
'weight' => 20,
'description' => 'Pictures settings',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'picture_admin_settings',
),
'access arguments' => array(
'administer pictures',
),
'file' => 'picture.admin.inc',
);
$items['admin/config/media/picture/groups/global'] = array(
'title' => 'Map breakpoints and image styles',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -1,
);
$items['admin/config/media/picture/groups/import'] = array(
'title' => 'Import mappings',
'page arguments' => array(
'picture_admin_import_form',
),
'type' => MENU_LOCAL_TASK,
'access arguments' => array(
'administer pictures',
),
'file' => 'picture.admin.inc',
'weight' => 999,
);
$breakpoint_groups = breakpoints_breakpoint_group_load_all();
foreach ($breakpoint_groups as $breakpoint_group_name => $breakpoint_group) {
if (!empty($breakpoint_group->machine_name)) {
$items['admin/config/media/picture/groups/' . $breakpoint_group->machine_name] = array(
'title' => $breakpoint_group->name,
'page arguments' => array(
'picture_admin_breakpoints',
$breakpoint_group->machine_name,
),
'type' => MENU_LOCAL_TASK,
'access arguments' => array(
'administer pictures',
),
'file' => 'picture.admin.inc',
'weight' => 15,
);
$items['admin/config/media/picture/groups/' . $breakpoint_group->machine_name . '/export'] = array(
'title' => 'Export ' . check_plain($breakpoint_group->name) . ' mappings',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'picture_admin_export_form',
$breakpoint_group->machine_name,
),
'type' => MENU_LOCAL_ACTION,
'access arguments' => array(
'administer pictures',
$breakpoint_group->machine_name,
),
'access callback' => 'picture_mappings_export_access',
'file' => 'picture.admin.inc',
'weight' => 15,
);
}
}
$items['admin/config/media/picture/ckeditor'] = array(
'title' => 'CKEditor',
'type' => MENU_LOCAL_TASK,
'description' => 'Choose picture groups to present in the CKEditor image dialog',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'picture_ckeditor_settings',
),
'access arguments' => array(
'administer pictures',
),
'file' => 'picture.admin.inc',
'weight' => 0,
);
return $items;
}
/**
* Access callback.
*/
function picture_mappings_export_access($perm, $mapping_name) {
return picture_mapping_load($mapping_name) && user_access($perm);
}
/**
* Load mappings.
*/
function picture_mapping_load($name = NULL) {
ctools_include('export');
if ($name) {
$mappings = ctools_export_load_object('picture_mapping', 'names', array(
$name,
));
$mapping = isset($mappings[$name]) ? $mappings[$name] : FALSE;
return $mapping;
}
return ctools_export_load_object('picture_mapping');
}
/**
* Load all mappings.
*/
function picture_mapping_load_all() {
ctools_include('export');
return ctools_export_load_object('picture_mapping');
}
/**
* Save mappings.
*/
function picture_mapping_save(&$mapping) {
ctools_include('export');
$update = isset($mapping->id) ? array(
'id',
) : array();
return drupal_write_record('picture_mapping', $mapping, $update);
}
/**
* Implements hook_library().
*/
function picture_library() {
$libraries = array();
switch (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT)) {
case PICTURE_IMPLEMENTATION_PICTUREFILL2:
$libraries['picturefill'] = array(
'title' => t('Picturefill'),
'website' => 'https://github.com/scottjehl/picturefill',
'version' => '2.0',
'js' => array(
drupal_get_path('module', 'picture') . '/picturefill2/picturefill.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
);
break;
case PICTURE_IMPLEMENTATION_PICTUREFILL:
$libraries['matchmedia'] = array(
'title' => t('Matchmedia'),
'website' => 'https://github.com/attiks/picturefill-proposal',
'version' => '0.1',
'js' => array(
drupal_get_path('module', 'picture') . '/picturefill/matchmedia.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
);
$libraries['picturefill'] = array(
'title' => t('Picturefill'),
'website' => 'https://github.com/attiks/picturefill-proposal',
'version' => '0.1',
'js' => array(
drupal_get_path('module', 'picture') . '/picturefill/picturefill.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
);
$libraries['picture.ajax'] = array(
'title' => t('Ajax support for picture'),
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'picture') . '/picture.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
);
break;
case PICTURE_IMPLEMENTATION_WEBLINC:
$libraries['matchmedia'] = array(
'title' => t('Matchmedia'),
'website' => 'https://github.com/weblinc/media-match',
'version' => '0.1',
'js' => array(
drupal_get_path('module', 'picture') . '/weblinc/media.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
drupal_get_path('module', 'picture') . '/weblinc/media.extension.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
'css' => array(
drupal_get_path('module', 'picture') . '/weblinc/media.css' => array(
'type' => 'file',
),
),
);
$libraries['picturefill'] = array(
'title' => t('Picturefill'),
'website' => 'https://github.com/weblinc/picture',
'version' => '0.1',
'js' => array(
drupal_get_path('module', 'picture') . '/weblinc/picture.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
);
$libraries['picture.ajax'] = array(
'title' => t('Ajax support for picture'),
'version' => VERSION,
'js' => array(
drupal_get_path('module', 'picture') . '/picture.weblinc.js' => array(
'type' => 'file',
'weight' => -10,
'group' => JS_DEFAULT,
'scope' => 'footer',
'need_jquery' => FALSE,
),
),
'css' => array(
drupal_get_path('module', 'picture') . '/picture.weblinc.css' => array(
'type' => 'file',
),
),
);
break;
}
return $libraries;
}
/**
* Empty picture object.
*/
function picture_empty_object() {
return (object) picture_empty_array();
}
/**
* Empty picture array.
*/
function picture_empty_array() {
return array(
'machine_name' => '',
'breakpoint_group' => '',
'mapping' => array(),
);
}
/**
* Validate mappings.
*/
function picture_mapping_validate($mapping) {
if (!is_object($mapping)) {
return FALSE;
}
foreach (array(
'machine_name',
'breakpoint_group',
'mapping',
) as $property) {
if (!property_exists($mapping, $property)) {
return FALSE;
}
}
return TRUE;
}
/**
* Implements hook_theme().
*/
function picture_theme() {
return array(
'picture' => array(
'variables' => array(
'style_name' => NULL,
'path' => 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,
'attributes' => array(),
'breakpoints' => array(),
),
),
'picture_formatter_colorbox' => array(
'variables' => array(
'item' => NULL,
'path' => NULL,
'image_style' => NULL,
'breakpoints' => array(),
'colorbox_group' => array(),
'colorbox_image_style' => NULL,
'colorbox_group_id' => NULL,
'colorbox_caption' => NULL,
),
),
'picture_source' => array(
'variables' => array(
'src' => NULL,
'dimension' => NULL,
'media' => NULL,
),
),
);
}
/**
* Implements hook_field_formatter_info().
*/
function picture_field_formatter_info() {
$formatters = array(
'picture' => array(
'label' => t('Picture'),
'field types' => array(
'image',
),
'settings' => array(
'picture_group' => '',
'fallback_image_style' => '',
'image_link' => '',
'colorbox_settings' => array(
'colorbox_group' => '',
'colorbox_gallery' => 'post',
'colorbox_gallery_custom' => '',
'colorbox_caption' => 'auto',
'colorbox_caption_custom' => '',
'colorbox_multivalue_index' => NULL,
),
),
),
);
return $formatters;
}
/**
* Implements hook_field_formatter_settings_form().
*/
function picture_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$options = picture_get_mapping_options();
if ($options) {
$element['picture_group'] = array(
'#title' => t('Picture group'),
'#type' => 'select',
'#default_value' => $settings['picture_group'],
'#required' => TRUE,
'#options' => $options,
);
}
else {
$element['picture_group'] = array(
'#title' => t('Picture group'),
'#type' => 'item',
'#markup' => t('There are no picture groups defined. !create_link.', array(
'!create_link' => l(t('Create a picture group'), 'admin/config/media/picture'),
)),
);
}
$image_styles = image_style_options(FALSE);
$element['fallback_image_style'] = array(
'#title' => t('Fallback image style'),
'#type' => 'select',
'#default_value' => $settings['fallback_image_style'],
'#empty_option' => t('Automatic'),
'#options' => $image_styles,
);
$link_types = picture_link_types($instance);
$element['image_link'] = array(
'#title' => t('Link image to'),
'#type' => 'select',
'#default_value' => $settings['image_link'],
'#empty_option' => t('Nothing'),
'#options' => $link_types,
'#attributes' => array(
'class' => array(
'picture-image-link',
),
),
);
// Settings for the colorbox option.
$element['colorbox_settings'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Colorbox settings'),
'#collapsed' => FALSE,
'#collapsible' => TRUE,
'#states' => array(
'visible' => array(
':input[name$="[settings][image_link]"].picture-image-link' => array(
'value' => 'colorbox',
),
),
),
);
$element['colorbox_settings']['colorbox_group'] = array(
'#title' => t('Colorbox group'),
'#type' => 'select',
'#default_value' => $settings['colorbox_settings']['colorbox_group'],
'#required' => FALSE,
'#options' => picture_get_mapping_options(),
);
$gallery = array(
'post' => t('Per post gallery'),
'page' => t('Per page gallery'),
'field_post' => t('Per field in post gallery'),
'field_page' => t('Per field in page gallery'),
'custom' => t('Custom'),
'none' => t('No gallery'),
);
$element['colorbox_settings']['colorbox_gallery'] = array(
'#title' => t('Gallery (image grouping)'),
'#type' => 'select',
'#default_value' => $settings['colorbox_settings']['colorbox_gallery'],
'#options' => $gallery,
'#description' => t('How Colorbox should group the image galleries.'),
'#attributes' => array(
'class' => array(
'picture-colorbox-gallery',
),
),
);
$element['colorbox_settings']['colorbox_gallery_custom'] = array(
'#title' => t('Custom gallery'),
'#type' => 'textfield',
'#maxlength' => 32,
'#default_value' => $settings['colorbox_settings']['colorbox_gallery_custom'],
'#description' => t('All images on a page with the same gallery value (rel attribute) will be grouped together. It must only contain lowercase letters, numbers, hyphen and underscores.'),
'#element_validate' => array(
'colorbox_gallery_custom_validate',
),
'#required' => FALSE,
'#states' => array(
'visible' => array(
':input[name$="[settings][colorbox_settings][colorbox_gallery]"].picture-colorbox-gallery' => array(
'value' => 'custom',
),
),
),
);
$caption = array(
'auto' => t('Automatic'),
'title' => t('Title text'),
'alt' => t('Alt text'),
'node_title' => t('Content title'),
'custom' => t('Custom (with tokens)'),
'none' => t('None'),
);
$element['colorbox_settings']['colorbox_caption'] = array(
'#title' => t('Caption'),
'#type' => 'select',
'#default_value' => $settings['colorbox_settings']['colorbox_caption'],
'#options' => $caption,
'#description' => t('Automatic will use the first none empty value of the title, the alt text and the content title.'),
'#attributes' => array(
'class' => array(
'picture-colorbox-caption',
),
),
);
$element['colorbox_settings']['colorbox_caption_custom'] = array(
'#title' => t('Custom caption'),
'#type' => 'textfield',
'#default_value' => $settings['colorbox_settings']['colorbox_caption_custom'],
'#states' => array(
'visible' => array(
':input[name$="[settings][colorbox_settings][colorbox_caption]"].picture-colorbox-caption' => array(
'value' => 'custom',
),
),
),
);
// Allow users to hide or set a custom recursion limit.
// The module token_tweaks sets a global recursion limit that can not be bypassed.
if (module_exists('token') && ($recursion_limit = min(variable_get('token_tree_recursion_limit', 3), variable_get('colorbox_token_recursion_limit', 3)))) {
$element['colorbox_settings']['colorbox_token'] = array(
'#type' => 'fieldset',
'#title' => t('Replacement patterns'),
'#theme' => 'token_tree',
'#token_types' => array(
$instance['entity_type'],
'file',
),
'#recursion_limit' => $recursion_limit,
'#dialog' => TRUE,
'#states' => array(
'visible' => array(
':input[name$="[settings][colorbox_settings][colorbox_caption]"].picture-colorbox-caption' => array(
'value' => 'custom',
),
),
),
);
}
else {
$element['colorbox_settings']['colorbox_token'] = array(
'#type' => 'fieldset',
'#title' => t('Replacement patterns'),
'#description' => '<strong class="error">' . t('For token support the <a href="@token_url">token module</a> must be installed.', array(
'@token_url' => 'http://drupal.org/project/token',
)) . '</strong>',
'#states' => array(
'visible' => array(
':input[name$="[settings][colorbox_settings][colorbox_caption]"].picture-colorbox-caption' => array(
'value' => 'custom',
),
),
),
);
}
return $element;
}
/**
* Returns a list of picture mappings for use in a select list.
*/
function picture_get_mapping_options() {
$picture_mapping_options = array();
$picture_mappings = picture_mapping_load_all();
if ($picture_mappings && !empty($picture_mappings)) {
foreach ($picture_mappings as $machine_name => $picture_mapping) {
$breakpoint_group = breakpoints_breakpoint_group_load($picture_mapping->breakpoint_group);
if ($breakpoint_group) {
$picture_mapping_options[$machine_name] = $breakpoint_group->name;
}
}
}
return $picture_mapping_options;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function picture_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$summary = array();
if (isset($settings['picture_group']) && !empty($settings['picture_group'])) {
$picture_mapping = picture_mapping_load($settings['picture_group']);
$breakpoint_group = breakpoints_breakpoint_group_load($picture_mapping->breakpoint_group);
if ($breakpoint_group) {
$summary[] = t('Picture group: @picture_group', array(
'@picture_group' => $breakpoint_group->name,
));
}
else {
$summary[] = t("Picture group doesn't exists");
}
}
else {
$summary[] = t("You have to select a mapping first.");
}
$image_styles = image_style_options(FALSE);
unset($image_styles['']);
if (isset($image_styles[$settings['fallback_image_style']])) {
$summary[] = t('Fallback Image style: @style', array(
'@style' => $image_styles[$settings['fallback_image_style']],
));
}
else {
$summary[] = t('Automatic fallback');
}
$link_types = picture_link_types($instance);
// Display this setting only if image is linked.
if (isset($link_types[$settings['image_link']])) {
$summary[] = filter_xss_admin($link_types[$settings['image_link']]);
}
// Display the settings for the colorbox if chosen.
if ($settings['image_link'] == 'colorbox') {
$summary[] = t('Colorbox Group: @setting', array(
'@setting' => $settings['colorbox_settings']['colorbox_group'],
));
$gallery = array(
'post' => t('Per post gallery'),
'page' => t('Per page gallery'),
'field_post' => t('Per field in post gallery'),
'field_page' => t('Per field in page gallery'),
'custom' => t('Custom'),
'none' => t('No gallery'),
);
$summary[] = t('Colorbox Gallery: @setting', array(
'@setting' => $gallery[$settings['colorbox_settings']['colorbox_gallery']],
));
if ($settings['colorbox_settings']['colorbox_gallery'] == 'custom') {
$summary[] = '→ ' . t('Colorbox Gallery Custom: @setting', array(
'@setting' => $settings['colorbox_settings']['colorbox_gallery_custom'],
));
}
$caption = array(
'auto' => t('Automatic'),
'title' => t('Title text'),
'alt' => t('Alt text'),
'node_title' => t('Content title'),
'custom' => t('Custom (with tokens)'),
'none' => t('None'),
);
$summary[] = t('Colorbox Caption: @setting', array(
'@setting' => $caption[$settings['colorbox_settings']['colorbox_caption']],
));
if ($settings['colorbox_settings']['colorbox_caption'] == 'custom') {
$summary[] = '→ ' . t('Colorbox Caption Custom: @setting', array(
'@setting' => $settings['colorbox_settings']['colorbox_caption_custom'],
));
}
}
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_view().
*/
function picture_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
// Check if the formatter involves a link.
$image_link = $display['settings']['image_link'];
if ($image_link == 'content') {
$uri = entity_uri($entity_type, $entity);
}
elseif ($image_link == 'file') {
$link_file = TRUE;
}
elseif ($image_link) {
if (isset($entity->{$image_link})) {
// Support for field translations.
$language = field_language($entity_type, $entity, $field['field_name']);
$link_field = $entity->{$image_link};
if (isset($link_field[$language])) {
$link_values = $link_field[$language];
}
}
}
$fallback_image_style = '';
$mappings = picture_mapping_load($display['settings']['picture_group']);
$breakpoint_styles = picture_get_mapping_breakpoints($mappings, $fallback_image_style);
if (isset($display['settings']['fallback_image_style']) && !empty($display['settings']['fallback_image_style'])) {
$fallback_image_style = $display['settings']['fallback_image_style'];
}
// Assume regular display.
$formatter = 'picture_formatter';
$colorbox_breakpoints = array();
$colorbox_fallback_image_style = '';
// Check for colorbox link.
if (module_exists('colorbox') && $display['settings']['image_link'] == 'colorbox') {
$formatter = 'picture_formatter_colorbox';
$mappings = picture_mapping_load($display['settings']['colorbox_settings']['colorbox_group']);
$colorbox_breakpoints = picture_get_mapping_breakpoints($mappings, $colorbox_fallback_image_style);
}
foreach ($items as $delta => $item) {
if (isset($link_file)) {
$uri = array(
'path' => file_create_url($item['uri']),
'options' => array(),
);
}
// Handle multiple link with image values.
if (isset($link_values)) {
if (isset($link_values[$delta]['url'])) {
$uri = array(
'path' => $link_values[$delta]['url'],
'options' => array(
'attributes' => $link_values[$delta]['attributes'],
),
);
// Handle query fragment if there is any.
if (!empty($link_values[$delta]['query'])) {
$uri['options']['query'] = $link_values[$delta]['query'];
}
}
else {
unset($uri);
}
}
$element[$delta] = array(
'#theme' => $formatter,
'#attached' => array(
'library' => array(
array(
'picture',
'matchmedia',
),
array(
'picture',
'picturefill',
),
array(
'picture',
'picture.ajax',
),
),
),
'#item' => $item,
'#image_style' => $fallback_image_style,
'#breakpoints' => $breakpoint_styles,
'#path' => isset($uri) ? $uri : '',
'#colorbox_group' => $colorbox_breakpoints,
'#colorbox_image_style' => $colorbox_fallback_image_style,
);
// Add css and js for colorbox.
if ($formatter == 'picture_formatter_colorbox') {
$element[$delta]['#attached']['css'][drupal_get_path('module', 'picture') . '/picture_colorbox.css'] = array(
'type' => 'file',
);
$element[$delta]['#attached']['js'][drupal_get_path('module', 'picture') . '/picture_colorbox.js'] = array(
'type' => 'file',
);
if (!variable_get('colorbox_inline', 0)) {
$element[$delta]['#attached']['js'][drupal_get_path('module', 'colorbox') . '/js/colorbox_inline.js'] = array(
'type' => 'file',
);
}
$colorbox_settings = $display['settings']['colorbox_settings'];
// Add the group ID.
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
$entity_id = !empty($id) ? $entity_type . '-' . $id : 'entity-id';
// If this is a file entity field check for the referencing entity to do
// the proper grouping.
if (isset($entity->referencing_entity) && isset($entity->referencing_field)) {
// Because we don't have the entity type we use some "magic" to get a
// unique entity identifier.
$entity_id = spl_object_hash($entity->referencing_entity);
$colorbox_group_field = $entity->referencing_field;
}
else {
$colorbox_group_field = $field['field_name'];
}
switch ($colorbox_settings['colorbox_gallery']) {
case 'post':
$gallery_id = 'gallery-' . $entity_id;
break;
case 'page':
$gallery_id = 'gallery-all';
break;
case 'field_post':
$gallery_id = 'gallery-' . $entity_id . '-' . $colorbox_group_field;
break;
case 'field_page':
$gallery_id = 'gallery-' . $colorbox_group_field;
break;
case 'custom':
$gallery_id = $colorbox_settings['colorbox_gallery_custom'];
break;
default:
$gallery_id = '';
}
$element[$delta]['#colorbox_group_id'] = $gallery_id;
// Add the caption.
$entity_title = entity_label($entity_type, $entity);
switch ($colorbox_settings['colorbox_caption']) {
case 'auto':
// If the title is empty use alt or the entity title in that order.
if (!empty($item['title'])) {
$caption = $item['title'];
}
elseif (!empty($item['alt'])) {
$caption = $item['alt'];
}
elseif (!empty($entity_title)) {
$caption = $entity_title;
}
else {
$caption = '';
}
break;
case 'title':
$caption = $item['title'];
break;
case 'alt':
$caption = $item['alt'];
break;
case 'node_title':
$caption = $entity_title;
break;
case 'custom':
$caption = token_replace($colorbox_settings['colorbox_caption_custom'], array(
$entity_type => $entity,
'file' => (object) $item,
), array(
'clear' => TRUE,
));
break;
default:
$caption = '';
}
// Shorten the caption for the example styles or when caption shortening
// is active.
$colorbox_style = variable_get('colorbox_style', 'default');
$trim_length = variable_get('colorbox_caption_trim_length', 75);
if ((strpos($colorbox_style, 'colorbox/example') !== FALSE || variable_get('colorbox_caption_trim', 0)) && drupal_strlen($caption) > $trim_length) {
$caption = drupal_substr($caption, 0, $trim_length - 5) . '...';
}
$element[$delta]['#colorbox_caption'] = $caption;
}
}
return $element;
}
/**
* Theme picture.
*/
function theme_picture_formatter($variables) {
if (!isset($variables['breakpoints']) || empty($variables['breakpoints'])) {
return theme('image_formatter', $variables);
}
$item = $variables['item'];
// Do not output an empty 'title' attribute.
if (isset($item['title']) && drupal_strlen($item['title']) == 0) {
unset($item['title']);
}
$item['style_name'] = $variables['image_style'];
$item['breakpoints'] = $variables['breakpoints'];
$item['attributes'] = $variables['attributes'];
if (!isset($item['path']) && isset($variables['uri'])) {
$item['path'] = $variables['uri'];
}
$output = theme('picture', $item);
if (is_array($variables['path']) && isset($variables['path']['path'])) {
$path = $variables['path']['path'];
$options = isset($variables['path']['options']) ? $variables['path']['options'] : array();
$options['html'] = TRUE;
$output = l($output, $path, $options);
}
return $output;
}
/**
* Theme function to add support for colorbox.
*/
function theme_picture_formatter_colorbox($variables) {
if (!isset($variables['breakpoints']) || empty($variables['breakpoints'])) {
return theme('image_formatter', $variables);
}
$item = $variables['item'];
// Do not output an empty 'title' attribute.
if (isset($item['title']) && drupal_strlen($item['title']) == 0) {
unset($item['title']);
}
$item['style_name'] = $variables['image_style'];
$item['breakpoints'] = $variables['breakpoints'];
if (!isset($item['path']) && isset($variables['uri'])) {
$item['path'] = $variables['uri'];
}
$output = theme('picture', $item);
if (isset($variables['colorbox_group'])) {
$item['breakpoints'] = $variables['colorbox_group'];
$item['style_name'] = $variables['colorbox_image_style'];
$id = 'picture-colorbox-' . user_password();
$colorbox = '<div style="display: none;"><div id="' . $id . '" class="picture-colorbox-container">' . theme('picture', $item) . '</div></div>';
$options = array(
'attributes' => array(
'class' => array(
'colorbox-inline',
),
),
'query' => array(
'maxWidth' => '80%',
'maxHeight' => '80%',
'inline' => 'true',
),
'fragment' => $id,
'html' => TRUE,
);
if (!empty($variables['colorbox_group_id'])) {
$options['attributes']['rel'] = $variables['colorbox_group_id'];
}
if (!empty($variables['colorbox_caption'])) {
$options['query']['title'] = $variables['colorbox_caption'];
}
// Do not load picture automatically.
$colorbox = str_replace('span data-picture=""', 'span data-picture-lazy="lazy"', $colorbox);
$output = l($output, current_path(), $options) . $colorbox;
}
return $output;
}
/**
* 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.
* - attributes: An array containing attributes.
*
* @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 (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) !== PICTURE_IMPLEMENTATION_PICTUREFILL2) {
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']);
}
if (isset($variables['metadata']['width']) && isset($variables['metadata']['height'])) {
$variables['width'] = $variables['metadata']['width'];
$variables['height'] = $variables['metadata']['height'];
}
}
else {
unset($variables['width']);
unset($variables['height']);
}
$sources = array();
$output = array();
// Fallback image, output as source with media query.
$sources[] = array(
'src' => _picture_image_style_url($variables['style_name'], $variables['uri']),
'dimensions' => picture_get_image_dimensions($variables, 1),
);
// All breakpoints and multipliers.
foreach ($variables['breakpoints'] as $breakpoint_name => $multipliers) {
$breakpoint = breakpoints_breakpoint_load_by_fullkey($breakpoint_name);
if ($breakpoint) {
$new_sources = array();
switch (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT)) {
case PICTURE_IMPLEMENTATION_PICTUREFILL:
case PICTURE_IMPLEMENTATION_PICTUREFILL2:
case PICTURE_IMPLEMENTATION_WEBLINC:
foreach ($multipliers as $multiplier => $image_style) {
$new_source = $variables;
$new_source['style_name'] = $image_style;
$new_source['#media_query'] = $breakpoint->breakpoint;
$new_source['#multiplier'] = $multiplier;
$new_sources[] = $new_source;
}
// Only one image, use src.
if (count($new_sources) == 1) {
foreach ($new_sources as $new_source) {
$sources[] = array(
'src' => _picture_image_style_url($new_source['style_name'], $new_source['uri']),
'dimensions' => picture_get_image_dimensions($new_source, $new_source['#multiplier']),
'media' => $new_source['#media_query'],
);
}
}
else {
// Mutliple images, use srcset.
$srcset = array();
foreach ($new_sources as $new_source) {
$srcset[] = _picture_image_style_url($new_source['style_name'], $new_source['uri']) . ' ' . $new_source['#multiplier'];
}
$sources[] = array(
'srcset' => implode(', ', $srcset),
'dimensions' => picture_get_image_dimensions($new_sources[0], $new_sources[0]['#multiplier']),
'media' => $new_source['#media_query'],
);
}
break;
}
}
}
if (!empty($sources)) {
$attributes = array();
foreach (array(
'alt',
'title',
) as $key) {
$field = sprintf('field_file_image_%s_text', $key);
if (isset($variables[$key]) && !empty($variables[$key])) {
$attributes['data-' . $key] = decode_entities($variables[$key]);
}
elseif (isset($variables[$field]) && is_array($variables[$field]) && isset($variables[$field]['und'][0]['safe_value'])) {
$attributes['data-' . $key] = decode_entities($variables[$field]['und'][0]['safe_value']);
}
}
// Add attributes that are already prefixed by 'data-'
foreach (array(
'data-picture-group',
'data-picture-align',
) as $key) {
if (isset($variables[$key]) && !empty($variables[$key])) {
$attributes[$key] = $variables[$key];
}
}
// Add additional attributes passed in through the render array.
if (isset($variables['attributes']) && !empty($variables['attributes'])) {
$attributes = array_merge($attributes, $variables['attributes']);
}
if (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) === PICTURE_IMPLEMENTATION_PICTUREFILL2) {
$output[] = '<picture' . drupal_attributes($attributes) . '>';
}
else {
$output[] = '<span data-picture=""' . drupal_attributes($attributes) . '>';
}
// Add source tags to the output.
foreach ($sources as $source) {
$output[] = theme('picture_source', $source);
}
// Output the fallback image.
if (!empty($variables['uri'])) {
$variables['path'] = $variables['uri'];
}
if (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) === PICTURE_IMPLEMENTATION_PICTUREFILL2) {
$output[] = theme('image_style', $variables);
$output[] = '</picture>';
}
else {
$output[] = '<noscript>' . theme('image_style', $variables) . '</noscript>';
$output[] = '</span>';
}
return implode("\n", $output);
}
}
/**
* Generates the media query for multipliers of an image
*
* @param $multiplier
* A string containing the multiplier for which the media query is for.
*
* @param $breakpoint
* A string containing the breakpoint media query.
*
* @return sting
* The sting containing the media query for the multiplier.
*/
function picture_get_multiplier_media_query($multiplier, $breakpoint) {
$media_query = $breakpoint;
if ($multiplier != '1x') {
$multiplier_formatted = str_replace('x', '', $multiplier);
if (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) === PICTURE_IMPLEMENTATION_PICTUREFILL2) {
}
else {
$media_query = $breakpoint . ' and (min-device-pixel-ratio: ' . $multiplier_formatted . '), ';
$media_query .= $breakpoint . ' and (-o-min-device-pixel-ratio: ' . $multiplier_formatted . '), ';
$media_query .= $breakpoint . ' and (-webkit-min-device-pixel-ratio: ' . $multiplier_formatted . '), ';
$media_query .= $breakpoint . ' and (min-resolution: ' . $multiplier_formatted . 'dppx)';
}
}
return $media_query;
}
/**
* Returns HTML for a source tag.
*
* @param type $variables
* An associative array containing:
* - media: The media query to use.
* - 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();
// Convert width, height to data-width, data-height.
foreach (array(
'width',
'height',
) as $key) {
if (isset($variables['dimensions'][$key])) {
$variables['dimensions']['data-' . $key] = $variables['dimensions'][$key];
}
unset($variables['dimensions'][$key]);
}
if (isset($variables['media']) && !empty($variables['media'])) {
if (isset($variables['srcset']) && !empty($variables['srcset'])) {
if (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) === PICTURE_IMPLEMENTATION_PICTUREFILL2) {
$output[] = '<source media="' . $variables['media'] . '" srcset="' . $variables['srcset'] . '">';
}
else {
$output[] = '<span data-media="' . $variables['media'] . '" data-srcset="' . $variables['srcset'] . '" ' . drupal_attributes($variables['dimensions']) . '></span>';
}
}
else {
if (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) === PICTURE_IMPLEMENTATION_PICTUREFILL2) {
$output[] = '<source media="' . $variables['media'] . '" srcset="' . $variables['src'] . '">';
}
else {
$output[] = '<span data-media="' . $variables['media'] . '" data-src="' . $variables['src'] . '" ' . drupal_attributes($variables['dimensions']) . '></span>';
}
}
}
else {
if (variable_get('picture_implementation', PICTURE_IMPLEMENTATION_DEFAULT) === PICTURE_IMPLEMENTATION_PICTUREFILL2) {
//$output[] = '<source src="' . $variables['src'] . '"></source>';
}
else {
$output[] = '<span data-src="' . $variables['src'] . '" ' . drupal_attributes($variables['dimensions']) . '></span>';
}
}
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).
* @param $multiplier
* Multiplier from the source
*
* @return array
* Dimensions to be modified - an array with components width and height, in
* pixels.
*/
function picture_get_image_dimensions($variables, $multiplier = 1) {
// Determine the dimensions of the styled image.
$dimensions = array();
if (isset($variables['width'])) {
$dimensions['width'] = $variables['width'];
}
if (isset($variables['height'])) {
$dimensions['height'] = $variables['height'];
}
if ($variables['style_name'] == PICTURE_EMPTY_IMAGE) {
$dimensions = array(
'width' => 1,
'height' => 1,
);
}
elseif ($variables['style_name'] == PICTURE_ORIGINAL_IMAGE) {
// NOOP.
}
else {
image_style_transform_dimensions($variables['style_name'], $dimensions);
if ($multiplier != 0 && $multiplier != 1) {
$dimensions['width'] = ceil($dimensions['width'] / $multiplier);
$dimensions['height'] = ceil($dimensions['height'] / $multiplier);
}
}
return $dimensions;
}
/**
* Implements hook_filter_info().
*/
function picture_filter_info() {
$filters = array();
$filters['picture'] = array(
'title' => t('Make images responsive with the picture module'),
'description' => t('Replace img tags with markup that contains media width breakpoints. The appropriate image file size will be chosen.'),
'process callback' => '_picture_filter_process',
'tips callback' => '_picture_filter_tips',
'type' => 'FILTER_TYPE_TRANSFORM_REVERSIBLE',
);
return $filters;
}
/**
* Process callback for inline image filter.
*/
function _picture_filter_process($text, $filter) {
// Find all img tags with a data-picture-group attribute.
preg_match_all('/<img.*?data-picture-group=".*?>/i', $text, $images);
if (!empty($images[0])) {
foreach ($images[0] as $image) {
// Create the render array expected by theme_picture_formatter.
$image_render_array = _picture_filter_prepare_image($image);
if (!$image_render_array) {
continue;
}
// Get the responsive markup for this image.
$new_markup = theme('picture_formatter', $image_render_array);
// Replace the original img tag with the responsive markup.
$text = str_replace($image, $new_markup, $text);
}
}
return $text;
}
/**
* Prepares a Render Array for theme_picture_formatter().
* It is similar to picture_field_formatter_view()
* with modifications for inline images.
*
* @param $image
* An img tag
* @see picture_field_formatter_view()
*/
function _picture_filter_prepare_image($image) {
// Make sure the closing tag is right.
$image = str_replace('/>', '>', $image);
$image = str_replace('>', ' />', $image);
$image = htmlspecialchars($image);
// Parse the tag as xml.
$xml = simplexml_load_string('<image>' . html_entity_decode($image, ENT_QUOTES, "utf-8") . '</image>');
if (isset($xml->img[0]) && is_object($xml->img[0])) {
$attributes = array();
foreach ($xml->img[0]
->attributes() as $a => $b) {
$attributes[$a] = (string) $b;
}
}
$fallback_image_style = '';
$mappings = picture_mapping_load($attributes['data-picture-group']);
$breakpoint_styles = picture_get_mapping_breakpoints($mappings, $fallback_image_style);
// Make sure we have a src attribute.
if (!isset($attributes['src'])) {
return FALSE;
}
$src = $attributes['src'];
// Make sure we have map src to uri.
$uri = picture_image_uri($src);
if (!$uri) {
return FALSE;
}
$image_info = image_get_info($uri);
if (!$image_info) {
// It's not an image.
return FALSE;
}
$picture_groups = variable_get('picture_ckeditor_groups', array());
$image_render_array = array(
'#theme' => 'picture_formatter',
'#item' => array(
'style_name' => $picture_groups[$attributes['data-picture-group']]['fallback'],
'uri' => $uri,
'width' => $image_info['width'],
'height' => $image_info['height'],
'data-picture-group' => $attributes['data-picture-group'],
'data-picture-align' => isset($attributes['data-picture-align']) ? $attributes['data-picture-align'] : '',
'alt' => isset($attributes['alt']) ? $attributes['alt'] : '',
'title' => isset($attributes['title']) ? $attributes['title'] : '',
'filemime' => $image_info['mime_type'],
),
'#image_style' => $picture_groups[$attributes['data-picture-group']]['fallback'],
'#breakpoints' => $breakpoint_styles,
'#path' => '',
);
return $image_render_array;
}
/**
* Implements callback_filter_tips().
*/
function _picture_filter_tips($filter, $format, $long = FALSE) {
return t('Images with a data-picture-group attribute will be responsive, with a file size appropriate for the browser width.');
}
/**
* Implements hook_page_build().
*
* Add the image processing javascript to every page. This allows these scripts
* to get included in aggregation, which is probably good since there will be
* pictures needing this javascript on most pages. The library does not get
* added twice, even if it's attached to multiple fields that are also being
* displayed with responsive images. Maybe this should check that the
* page is not an admin theme page?
*/
function picture_page_build(&$page) {
drupal_add_library('picture', 'matchmedia', TRUE);
drupal_add_library('picture', 'picturefill', TRUE);
drupal_add_library('picture', 'picture.ajax', TRUE);
// Integrate with the WYSIWYG module, and the CKEditor module.
$picture_groups = picture_get_mapping_options();
$ckeditor_groups = variable_get('picture_ckeditor_groups', array());
$groups = array();
// CKEditor library expects an array of options formatted as
// ['Display name', 'machine_name'].
foreach ($ckeditor_groups as $machine_name => $parameters) {
if (array_key_exists($machine_name, $picture_groups)) {
if ($parameters['enabled'] == 1) {
$groups[] = array(
$picture_groups[$machine_name],
$machine_name,
);
}
}
}
if (!empty($groups)) {
$groups[] = array(
'Not Set',
'not_set',
);
drupal_add_js(array(
'picture' => array(
'groups' => $groups,
'label' => variable_get('picture_ckeditor_label', 'Image size (required)'),
),
), 'setting');
}
}
/**
* Helper function to figure out the uri of an image given the
* image src.
*
* @param
* Image src starting with http://, https://, or root relative /.
*/
function picture_image_uri($src) {
foreach (module_implements('picture_image_uri') as $module) {
$function = $module . '_picture_image_uri';
if ($uri = $function($src)) {
$uri = file_stream_wrapper_uri_normalize($uri);
return urldecode($uri);
}
}
return FALSE;
}
/**
* Implements hook_picture_image_uri().
*/
function picture_picture_image_uri($src) {
global $base_path;
$uri = '';
// Prepare the src by removing http:// or https://.
$src = parse_url($src, PHP_URL_PATH);
// Remove leading or trailing slashes.
$src = trim($src, '/');
// List all visible stream wrappers. Make sure they're also local since the
// getDirectoryPath method exists only for classes that extend
// DrupalLocalStreamWrapper.
$local_visible_stream_wrappers = array_intersect_key(file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL), file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE));
$needles = array();
$matches = array();
foreach ($local_visible_stream_wrappers as $scheme => $data) {
$class = file_stream_wrapper_get_class($scheme);
$stream_wrapper = new $class();
// Trim leading or trailing slashes since the Directory could be root
// relative.
$needles[$scheme] = trim($base_path . $stream_wrapper
->getDirectoryPath(), '/');
// Check whether the file stream directory is at the beginning of
// the image src. Use === since strpos could return false.
if (!empty($needles[$scheme]) && strpos($src, $needles[$scheme]) === 0) {
$matches[$scheme] = $needles[$scheme];
}
}
// No file stream wrapper is starting with the image src.
// So it's not a public file.
if (empty($matches)) {
// Check for managed/private file with relative path like 'system/files/...'.
$src_exploded = explode('/', $src);
if ($src_exploded[0] == 'system' && $src_exploded[1] == 'files') {
// Managed/private file recognized.
// Check for image style derivatives.
if ($src_exploded[2] == 'styles') {
// Image style recognized.
$unwanted_part = 'system/files/styles/' . $src_exploded[3] . '/private/';
$uri = str_replace($unwanted_part, 'private://', $src);
$uri = file_stream_wrapper_uri_normalize($uri);
return urldecode($uri);
}
else {
// No image style recognized; must be an original.
$unwanted_part = 'system/files/';
$uri = str_replace($unwanted_part, 'private://', $src);
$uri = file_stream_wrapper_uri_normalize($uri);
return urldecode($uri);
}
// It's not a managed/private file.
}
else {
// Can't figure out the Drupal uri.
return FALSE;
}
}
// If one file scheme directory is a subdirectory of another file
// scheme directory, choose the longer one. This issue is possible with
// the following scenario:
// public file dir: /sites/default/files/
// private file dir: /sites/default/files/private/
// image src: /sites/default/files/private/the-image.jpg
// In this example, the intended scheme would be 'private'.
// Find the length of each matching directory path.
$lengths = array_map('strlen', $matches);
// Determine the key of the longest one.
$the_scheme = array_search(max($lengths), $lengths);
// Construct the Drupal uri.
$uri = $the_scheme . '://' . str_replace($matches[$the_scheme], '', $src);
return $uri;
}
/**
* Implements hook_wysiwyg_plugin() to modify the CKEditor image dialog for use
* with the picture module.
*/
function picture_wysiwyg_plugin($editor, $version) {
if ($editor == 'ckeditor') {
return array(
'picture_ckeditor' => array(
'path' => drupal_get_path('module', 'picture') . '/plugins/',
'load' => TRUE,
'extensions' => array(
'picture_ckeditor' => t('Responsive images with the Picture Module'),
),
'url' => 'http://drupal.org/projects/picture',
),
);
}
}
/**
* Implements hook_ckeditor_plugin() to modify the CKEditor image dialog for use
* with the picture module.
*/
function picture_ckeditor_plugin() {
return array(
'picture_ckeditor' => array(
// Name of the plugin used to write it.
'name' => 'picture_ckeditor',
// Description of the plugin - it would be displayed in the plugins management section of profile settings.
'desc' => t('Support responsive images with the Picture module.'),
// The full path to the CKEditor plugins directory, with the trailing slash.
'buttons' => FALSE,
'path' => drupal_get_path('module', 'picture') . '/plugins/',
'default' => 't',
),
);
}
/**
* Wrapper around image_style_url() so we can return an empty image.
*/
function _picture_image_style_url($style_name, $path) {
if ($style_name == PICTURE_EMPTY_IMAGE) {
return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
}
if ($style_name == PICTURE_ORIGINAL_IMAGE) {
return file_create_url($path);
}
return image_style_url($style_name, $path);
}
/**
* Implements hook_wysiwyg_editor_settings_alter().
*/
function picture_wysiwyg_editor_settings_alter(&$settings, $context) {
if ($context['profile']->editor == 'ckeditor') {
if (!isset($settings['extraAllowedContent'])) {
$settings['extraAllowedContent'] = array(
'img[src,title,alt,style,width,height,class,hspace,vspace,view_mode,format,fid,data-picture-group,data-picture-align]',
);
}
else {
// @todo: try finding the img entry and add data- attributes if needed.
}
}
}
/**
* Returns a list with the image styles of a mapping configuration.
*
* @param object $mappings
* The mapping configuration.
* @param string $fallback_image_style
* Reference to access the evaluated fallback image style.
*
* @return array
* List with the image styles of a mapping configuration.
* The array has following structure:
* array(
* breakpoint_name => array(
* multiplier => image_style
* )
* )
*/
function picture_get_mapping_breakpoints($mappings, &$fallback_image_style = NULL) {
$breakpoint_styles = array();
if (is_object($mappings)) {
foreach ($mappings->mapping as $breakpoint_name => $multipliers) {
if (!empty($multipliers)) {
foreach ($multipliers as $multiplier => $image_style) {
if (!empty($image_style)) {
if (empty($fallback_image_style)) {
$fallback_image_style = $image_style;
}
if (!isset($breakpoint_styles[$breakpoint_name])) {
$breakpoint_styles[$breakpoint_name] = array();
}
$breakpoint_styles[$breakpoint_name][$multiplier] = $image_style;
}
}
}
}
}
return $breakpoint_styles;
}
/**
* Helper function to compute the list of possible link types.
*/
function picture_link_types($instance) {
$link_types = array(
'content' => t('Content'),
'file' => t('File'),
);
if (module_exists('colorbox')) {
$link_types['colorbox'] = t('Colorbox');
}
// If the link module is installed, also allow any link fields to be used.
foreach (field_info_fields() as $field_key => $field_info) {
if ($field_info['type'] == 'link_field') {
$field_instance = field_info_instance($instance['entity_type'], $field_info['field_name'], $instance['bundle']);
if ($field_instance) {
$link_types[$field_key] = "{$field_instance['label']} ({$field_info['field_name']})";
}
}
}
return $link_types;
}
Functions
Name | Description |
---|---|
picture_ckeditor_plugin | Implements hook_ckeditor_plugin() to modify the CKEditor image dialog for use with the picture module. |
picture_empty_array | Empty picture array. |
picture_empty_object | Empty picture object. |
picture_field_formatter_info | Implements hook_field_formatter_info(). |
picture_field_formatter_settings_form | Implements hook_field_formatter_settings_form(). |
picture_field_formatter_settings_summary | Implements hook_field_formatter_settings_summary(). |
picture_field_formatter_view | Implements hook_field_formatter_view(). |
picture_filter_info | Implements hook_filter_info(). |
picture_get_image_dimensions | Determines the dimensions of an image. |
picture_get_mapping_breakpoints | Returns a list with the image styles of a mapping configuration. |
picture_get_mapping_options | Returns a list of picture mappings for use in a select list. |
picture_get_multiplier_media_query | Generates the media query for multipliers of an image |
picture_image_uri | Helper function to figure out the uri of an image given the image src. |
picture_library | Implements hook_library(). |
picture_link_types | Helper function to compute the list of possible link types. |
picture_mappings_export_access | Access callback. |
picture_mapping_load | Load mappings. |
picture_mapping_load_all | Load all mappings. |
picture_mapping_save | Save mappings. |
picture_mapping_validate | Validate mappings. |
picture_menu | Implements hook_menu(). |
picture_page_build | Implements hook_page_build(). |
picture_permission | Implements hook_permission(). |
picture_picture_image_uri | Implements hook_picture_image_uri(). |
picture_theme | Implements hook_theme(). |
picture_wysiwyg_editor_settings_alter | Implements hook_wysiwyg_editor_settings_alter(). |
picture_wysiwyg_plugin | Implements hook_wysiwyg_plugin() to modify the CKEditor image dialog for use with the picture module. |
theme_picture | Returns HTML for a picture. |
theme_picture_formatter | Theme picture. |
theme_picture_formatter_colorbox | Theme function to add support for colorbox. |
theme_picture_source | Returns HTML for a source tag. |
_picture_filter_prepare_image | Prepares a Render Array for theme_picture_formatter(). It is similar to picture_field_formatter_view() with modifications for inline images. |
_picture_filter_process | Process callback for inline image filter. |
_picture_filter_tips | Implements callback_filter_tips(). |
_picture_image_style_url | Wrapper around image_style_url() so we can return an empty image. |