You are here

image_field_caption.module in Image Field Caption 7.2

Same filename and directory in other branches
  1. 8 image_field_caption.module
  2. 7 image_field_caption.module

Provides a caption textarea for image fields.

File

image_field_caption.module
View source
<?php

/**
 * @file
 * Provides a caption textarea for image fields.
 */

/**
 * Implements hook_theme_registry_alter().
 */
function image_field_caption_theme_registry_alter(&$theme_registry) {

  // Override the image_formatter function and add caption as a variable to be
  // assembled by theme().
  $theme_registry['image_formatter']['theme path'] = drupal_get_path('module', 'image_field_caption');
  $theme_registry['image_formatter']['function'] = 'image_field_caption_image_formatter';
  $theme_registry['picture_formatter']['function'] = 'image_field_caption_picture_formatter';
  $theme_registry['picture_sizes_formatter']['function'] = 'image_field_caption_picture_sizes_formatter';
}

/**
 * Override of theme_image_formatter().
 */
function image_field_caption_image_formatter($variables) {
  $image = theme_image_formatter($variables);

  // Now that Drupal has rendered the image, if there was a caption let's
  // render the image and the caption, otherwise just return the already
  // rendered image.
  if (isset($variables['item']['image_field_caption']) && !empty($variables['item']['image_field_caption']['value'])) {
    return theme('image_field_caption', array(
      'image' => $image,
      'caption' => check_markup($variables['item']['image_field_caption']['value'], $variables['item']['image_field_caption']['format']),
    ));
  }
  else {
    return $image;
  }
}

/**
 * Override of theme_picture_formatter().
 */
function image_field_caption_picture_formatter($variables) {
  $image = theme_picture_formatter($variables);

  // Now that Drupal has rendered the image, if there was a caption let's
  // render the image and the caption, otherwise just return the already
  // rendered image.
  if (isset($variables['item']['image_field_caption']) && !empty($variables['item']['image_field_caption']['value'])) {
    return theme('image_field_caption', array(
      'image' => $image,
      'caption' => check_markup($variables['item']['image_field_caption']['value'], $variables['item']['image_field_caption']['format']),
    ));
  }
  else {
    return $image;
  }
}

/**
 * Override of theme_picture_sizes_formatter().
 */
function image_field_caption_picture_sizes_formatter($variables) {
  $image = theme_picture_sizes_formatter($variables);

  // Now that Drupal has rendered the image, if there was a caption let's
  // render the image and the caption, otherwise just return the already
  // rendered image.
  if (isset($variables['item']['image_field_caption']) && !empty($variables['item']['image_field_caption']['value'])) {
    return theme('image_field_caption', array(
      'image' => $image,
      'caption' => check_markup($variables['item']['image_field_caption']['value'], $variables['item']['image_field_caption']['format']),
    ));
  }
  else {
    return $image;
  }
}

/**
 * Implements hook_theme().
 */
function image_field_caption_theme($existing, $type, $theme, $path) {
  return array(
    'image_field_caption' => array(
      'template' => 'image_field_caption',
      'variables' => array(
        'image' => NULL,
        'caption' => NULL,
      ),
    ),
  );
}

/**
 * Given an entity type and bundle name, this will return an associative array
 * of image field info instances, keyed by image field machine names. Returns
 * null if no image fields are found.
 */
function image_field_caption_get_image_fields($entity_type = NULL, $bundle = NULL) {

  // TODO: As of Drupal 7.22 use field_info_field_map() instead of field_info_instances();
  $image_fields = array();
  $fields = field_info_instances($entity_type, $bundle);
  foreach ($fields as $field_name => $field) {

    // Skip any deleted and non image widget fields.
    if ($field['deleted'] == 1) {
      continue;
    }
    $field_info = field_info_field($field_name);
    if ($field_info['type'] != 'image') {
      continue;
    }
    $image_fields[$field_name] = $field;
  }
  return $image_fields;
}

/**
 * Implements hook_form_alter().
 */
function image_field_caption_form_field_ui_field_edit_form_alter(&$form, $form_state) {
  $instance = $form['#instance'];
  $field = $form['#field'];
  if ($field['type'] == 'image') {
    $field = $form['#field'];
    if (empty($form['instance']['settings'])) {
      $form['instance']['settings'] = array();
    }
    $form['instance']['settings'] += image_field_caption_field_instance_settings_form($field, $instance);
  }
}

/**
 * Configuration form for editing insert settings for a field instance.
 */
function image_field_caption_field_instance_settings_form($field, $instance) {
  $form['image_field_caption'] = array(
    '#type' => 'fieldset',
    '#title' => t('Caption Settings'),
    '#weight' => 12,
    '#collapsible' => FALSE,
    '#collapsed' => FALSE,
  );
  $form['image_field_caption']['enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable Caption'),
    '#default_value' => $instance['settings']['image_field_caption']['enabled'],
    '#description' => t('Adds an extra text area for captions on image fields.'),
    '#weight' => 12,
  );
  $form['image_field_caption_wrapper'] = array(
    '#type' => 'fieldset',
    '#title' => t('Image field caption settings'),
    '#weight' => 12.1,
    '#collapsible' => FALSE,
    '#collapsed' => FALSE,
    '#states' => array(
      'visible' => array(
        ':input[name="instance[settings][image_field_caption][enabled]"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $form['image_field_caption_wrapper']['image_field_caption_default'] = array(
    '#type' => 'text_format',
    '#title' => t('Default caption text'),
    '#default_value' => $instance['settings']['image_field_caption_wrapper']['image_field_caption_default']['value'],
    '#format' => $instance['settings']['image_field_caption_wrapper']['image_field_caption_default']['format'],
    '#weight' => 12.1,
  );
  return $form;
}
function image_field_caption_field_widget_form_alter(&$element, &$form_state, $context) {

  // Add display_field setting to field because file_field_widget_form() assumes it is set.
  $instance = $context['instance'];
  $settings = $instance['settings'];
  $field = $context['field'];
  if (isset($settings['image_field_caption']['enabled']) && $field['type'] == 'image' && $settings['image_field_caption']['enabled']) {
    foreach (element_children($element) as $delta) {

      // Add all extra functionality provided by the image widget.
      $element[$delta]['#process'][] = 'image_field_caption_widget_process';
      $element[$delta]['#settings']['image_field_caption_default'] = $settings['image_field_caption_wrapper']['image_field_caption_default'];
    }
  }
}

/**
 * An element #process callback for the image field type.
 *
 * Expands the image type to include the caption.
 */
function image_field_caption_widget_process($element, &$form_state, $form) {
  $item = $element['#value'];

  // Add the caption field with its value and text format. If there is no file
  // uri then we'll use the instance setting defaults, otherwise there is no
  // way to tell if this is a new image or not.
  $element['image_field_caption'] = array(
    '#title' => t('Caption'),
    '#type' => 'text_format',
    '#default_value' => isset($item['image_field_caption']['value']) ? $item['image_field_caption']['value'] : $element['#settings']['image_field_caption_default']['value'],
    '#access' => (bool) $item['fid'],
    '#format' => isset($item['image_field_caption']['format']) ? $item['image_field_caption']['format'] : $element['#settings']['image_field_caption_default']['format'],
  );
  return $element;
}
function image_field_caption_field_info_alter(&$info) {

  // Add a setting to all field types.
  foreach ($info as $field_type => $field_type_info) {
    if ($field_type == 'image') {
      $info['image']['instance_settings'] += array(
        'image_field_caption' => array(
          'enabled' => 0,
        ),
        'image_field_caption_wrapper' => array(
          'image_field_caption_default' => array(
            'value' => '',
            'format' => filter_default_format(),
          ),
        ),
      );
    }
  }
}

/**
 * Implements hook_field_attach_insert().
 */
function image_field_caption_field_attach_insert($entity_type, $entity) {
  image_field_caption_field_attach_update($entity_type, $entity);
}

/**
 * Implements hook_field_attach_update().
 */
function image_field_caption_field_attach_update($entity_type, $entity) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  if (!isset($vid)) {
    $vid = $id;
  }
  $image_fields = image_field_caption_get_image_fields($entity_type, $bundle);
  foreach ($image_fields as $field_name => $image_field) {

    // Skip the caption when it isn't present, or if it is disabled.
    if (!isset($image_field['settings']['image_field_caption']) || !$image_field['settings']['image_field_caption']['enabled']) {
      continue;
    }
    $field = field_info_field($field_name);
    $table_name = 'field_image_field_caption';
    $revision_name = 'field_image_field_caption_revision';
    $all_languages = field_available_languages($entity_type, $field);
    if (!isset($entity->{$field_name})) {
      continue;
    }
    $field_languages = array_intersect($all_languages, array_keys((array) $entity->{$field_name}));

    // Delete and insert, rather than update, in case a value was added.
    // Delete languages present in the incoming $entity->$field_name.
    // Delete all languages if $entity->$field_name is empty.
    $languages = !empty($entity->{$field_name}) ? $field_languages : $all_languages;
    if ($languages) {
      db_delete($table_name)
        ->condition('field_name', $field_name)
        ->condition('entity_type', $entity_type)
        ->condition('entity_id', $id)
        ->condition('language', $languages, 'IN')
        ->execute();
      db_delete($revision_name)
        ->condition('field_name', $field_name)
        ->condition('entity_type', $entity_type)
        ->condition('entity_id', $id)
        ->condition('revision_id', $vid)
        ->condition('language', $languages, 'IN')
        ->execute();
    }

    // Prepare the multi-insert query.
    $do_insert = FALSE;
    $columns = array(
      'field_name',
      'entity_type',
      'entity_id',
      'revision_id',
      'bundle',
      'delta',
      'language',
      'caption',
      'caption_format',
    );
    $query = db_insert($table_name)
      ->fields($columns);
    $revision_query = db_insert($revision_name)
      ->fields($columns);
    foreach ($field_languages as $langcode) {
      $items = (array) $entity->{$field_name}[$langcode];
      $delta_count = 0;
      foreach ($items as $delta => $item) {
        if (empty($item['image_field_caption']['value'])) {
          continue;
        }

        // We now know we have someting to insert.
        $do_insert = TRUE;
        $record = array(
          'field_name' => $field_name,
          'entity_type' => $entity_type,
          'entity_id' => $id,
          'revision_id' => $vid,
          'bundle' => $bundle,
          'delta' => $delta,
          'language' => $langcode,
          'caption' => $item['image_field_caption']['value'],
          'caption_format' => $item['image_field_caption']['format'],
        );
        $query
          ->values($record);
        if (isset($vid)) {
          $revision_query
            ->values($record);
        }
        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
          break;
        }
      }
    }

    // Execute the query if we have values to insert.
    if ($do_insert) {
      $query
        ->execute();
      $revision_query
        ->execute();
    }
  }
}

/**
 * Implements hook_field_attach_load().
 */
function image_field_caption_field_attach_load($entity_type, $entities, $age, $options) {
  foreach ($entities as $entity) {
    list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
    if (!isset($vid)) {
      $vid = $id;
    }
    $load_current = $age == FIELD_LOAD_CURRENT;
    $table = $load_current ? 'field_image_field_caption' : 'field_image_field_caption_revision';
    $query = db_select($table, 't')
      ->fields('t')
      ->condition('entity_type', $entity_type)
      ->condition($load_current ? 'entity_id' : 'revision_id', $load_current ? $id : $vid)
      ->orderBy('delta');
    $results = $query
      ->execute();
    foreach ($results as $row) {
      $field = field_info_instance($entity_type, $row->field_name, $bundle);
      if (!isset($field['settings']['image_field_caption']) || !$field['settings']['image_field_caption']['enabled']) {
        continue;
      }
      $item['image_field_caption']['value'] = $row->caption;
      $item['image_field_caption']['format'] = $row->caption_format;

      // Add the item to the field values for the entity.
      $entities[$row->entity_id]->{$row->field_name}[$row->language][$row->delta]['image_field_caption']['value'] = $row->caption;
      $entities[$row->entity_id]->{$row->field_name}[$row->language][$row->delta]['image_field_caption']['format'] = $row->caption_format;
    }
  }
}

/**
 * Implements hook_field_attach_delete().
 */
function image_field_caption_field_attach_delete($entity_type, $entity) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  foreach (field_info_instances($entity_type, $bundle) as $instance) {
    $field = field_info_field_by_id($instance['field_id']);
    image_field_caption_field_attach_purge($entity_type, $entity, $field, $instance);
  }
}

/**
 * Implements hook_field_attach_purge().
 */
function image_field_caption_field_attach_purge($entity_type, $entity, $field, $instance) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  $field_name = is_object($field) ? $field->field_name : $field['field_name'];
  $table_name = 'field_image_field_caption';
  $revision_name = 'field_image_field_caption_revision';
  db_delete($table_name)
    ->condition('entity_type', $entity_type)
    ->condition('entity_id', $id)
    ->condition('field_name', $field_name)
    ->execute();
  db_delete($revision_name)
    ->condition('entity_type', $entity_type)
    ->condition('entity_id', $id)
    ->condition('field_name', $field_name)
    ->execute();
}

/**
 * Implements hook_field_attach_delete_revision().
 */
function image_field_caption_field_attach_delete_revision($entity_type, $entity) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  if (isset($vid)) {
    $revision_name = 'field_image_field_caption_revision';
    db_delete($revision_name)
      ->condition('entity_type', $entity_type)
      ->condition('entity_id', $id)
      ->condition('revision_id', $vid)
      ->execute();
  }
}

/**
 * Implements field_diff_view_alter().
 */
function image_field_caption_field_diff_view_alter(&$values, $items, $context) {
  $field = $context['field'];
  $instance = $context['instance'];
  $settings = $context['settings'];

  // Only handle image fields
  if ($field['type'] != 'image' || !$instance['settings']['image_field_caption']) {
    return;
  }
  foreach ($items as $delta => $item) {
    $format_id = empty($item['image_field_caption']['format']) ? filter_fallback_format() : $item['image_field_caption']['format'];
    if ($format = filter_format_load($format_id)) {
      $format_text = $format->name;
    }
    else {
      $format_text = t('Missing format !format', array(
        '!format' => $format_id,
      ));
    }
    if (!is_array($values[$delta])) {
      $values[$delta] = array(
        $values[$delta],
      );
    }
    $values[$delta][] = t('Caption (!text_format):', array(
      '!text_format' => $format_text,
    ));

    // Allow users to optionally clean system specific characters.
    $values[$delta][] = diff_normalise_text($item['image_field_caption']['value']);
  }
}

/**
 * Implements of hook_views_api().
 */
function image_field_caption_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'image_field_caption') . '/views',
  );
}

Functions

Namesort descending Description
image_field_caption_field_attach_delete Implements hook_field_attach_delete().
image_field_caption_field_attach_delete_revision Implements hook_field_attach_delete_revision().
image_field_caption_field_attach_insert Implements hook_field_attach_insert().
image_field_caption_field_attach_load Implements hook_field_attach_load().
image_field_caption_field_attach_purge Implements hook_field_attach_purge().
image_field_caption_field_attach_update Implements hook_field_attach_update().
image_field_caption_field_diff_view_alter Implements field_diff_view_alter().
image_field_caption_field_info_alter
image_field_caption_field_instance_settings_form Configuration form for editing insert settings for a field instance.
image_field_caption_field_widget_form_alter
image_field_caption_form_field_ui_field_edit_form_alter Implements hook_form_alter().
image_field_caption_get_image_fields Given an entity type and bundle name, this will return an associative array of image field info instances, keyed by image field machine names. Returns null if no image fields are found.
image_field_caption_image_formatter Override of theme_image_formatter().
image_field_caption_picture_formatter Override of theme_picture_formatter().
image_field_caption_picture_sizes_formatter Override of theme_picture_sizes_formatter().
image_field_caption_theme Implements hook_theme().
image_field_caption_theme_registry_alter Implements hook_theme_registry_alter().
image_field_caption_views_api Implements of hook_views_api().
image_field_caption_widget_process An element #process callback for the image field type.