<?php

/**
 * @file
 * Add an URL formatter for image field
 */

/**
 * Define constants for determine which type of URL should be used.
 */
define('IMAGE_URL_FORMATTER_URI_PATH', '3');
define('IMAGE_URL_FORMATTER_RELATIVE_PATH', '2');
define('IMAGE_URL_FORMATTER_ABSOLUTE_PATH', '1');
define('IMAGE_URL_FORMATTER_FULL_URL', '0');

/**
 * Implements hook_theme().
 */
function image_url_formatter_theme() {
  return array(
    'image_url_formatter' => array(
      'variables' => array(
        'item' => NULL,
        'path' => NULL,
        'image_style' => NULL,
        'url_type' => NULL,
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_info().
 */
function image_url_formatter_field_formatter_info() {
  $formatters = array(
    'image_url' => array(
      'label' => t('Image URL'),
      'field types' => array('image', 'imagefield_crop'),
      'settings' => array(
        'url_type' => '',
        'image_style' => '',
        'image_link' => '',
      ),
    ),
  );

  return $formatters;
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function image_url_formatter_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $element['url_type'] = array(
    '#title' => t('URL type'),
    '#type' => 'radios',
    '#options' => array(
      IMAGE_URL_FORMATTER_URI_PATH => t('URI path'),
      IMAGE_URL_FORMATTER_RELATIVE_PATH => t('Relative file path'),
      IMAGE_URL_FORMATTER_ABSOLUTE_PATH => t('Absolute file path (recommended)'),
      IMAGE_URL_FORMATTER_FULL_URL => t('Full URL'),
    ),
    '#default_value' => $settings['url_type'],
  );
  $element['url_type'][IMAGE_URL_FORMATTER_URI_PATH]['#description'] = t("Uses the URI path, like: 'public://image.png'");
  $element['url_type'][IMAGE_URL_FORMATTER_RELATIVE_PATH]['#description'] = t("No base URL or leading slash, like: 'sites/default/files/image.png'");
  $element['url_type'][IMAGE_URL_FORMATTER_ABSOLUTE_PATH]['#description'] = t("With leading slash, no base URL, like: '/sites/default/files/image.png'");
  $element['url_type'][IMAGE_URL_FORMATTER_FULL_URL]['#description'] = t("Like: 'http://example.com/sites/default/files/image.png'");

  $image_styles = image_style_options(FALSE);
  $element['image_style'] = array(
    '#title' => t('Image style'),
    '#type' => 'select',
    '#default_value' => $settings['image_style'],
    '#empty_option' => t('None (original image)'),
    '#options' => $image_styles,
  );

  $link_types = array(
    'content' => t('Content'),
    'file' => t('File'),
  );
  $element['image_link'] = array(
    '#title' => t('Link image url to'),
    '#type' => 'select',
    '#default_value' => $settings['image_link'],
    '#empty_option' => t('Nothing'),
    '#options' => $link_types,
  );

  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function image_url_formatter_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $summary = array();

  switch ($settings['url_type']) {
    case IMAGE_URL_FORMATTER_URI_PATH:
      $summary[] = t('Use uri path');
      break;

    case IMAGE_URL_FORMATTER_RELATIVE_PATH:
      $summary[] = t('Use relative path');
      break;

    case IMAGE_URL_FORMATTER_ABSOLUTE_PATH:
      $summary[] = t('Use absolute path');
      break;

    case IMAGE_URL_FORMATTER_FULL_URL:
      $summary[] = t('Use full URL');
      break;
  }

  $image_styles = image_style_options(FALSE);
  // Unset possible 'No defined styles' option.
  unset($image_styles['']);
  // Styles could be lost because of enabled/disabled modules that defines
  // their styles in code.
  if (isset($image_styles[$settings['image_style']])) {
    $summary[] = t('URL for image style: @style', array('@style' => $image_styles[$settings['image_style']]));
  }
  else {
    $summary[] = t('Original image URL');
  }

  $link_types = array(
    'content' => t('Linked to content'),
    'file' => t('Linked to file'),
  );
  // Display this setting only if image is linked.
  if (isset($link_types[$settings['image_link']])) {
    $summary[] = $link_types[$settings['image_link']];
  }

  return implode('<br />', $summary);
}
/**
 * Implements hook_field_formatter_view().
 */
function image_url_formatter_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();

  switch ($display['type']) {
    case 'image_url':
      // Check if the formatter involves a link.
      if ($display['settings']['image_link'] == 'content') {
        $uri = entity_uri($entity_type, $entity);
      }
      elseif ($display['settings']['image_link'] == 'file') {
        $link_file = TRUE;
      }

      foreach ($items as $delta => $item) {
        if (isset($link_file)) {
          $uri = array(
            'path' => file_create_url($item['uri']),
            'options' => array(),
          );
        }
        $element[$delta] = array(
          '#theme' => 'image_url_formatter',
          '#item' => $item,
          '#image_style' => $display['settings']['image_style'],
          '#path' => isset($uri) ? $uri : '',
          '#url_type' => $display['settings']['url_type'],
        );
      }

      break;

  }

  return $element;
}

/**
 * Returns HTML for an image url field formatter.
 *
 * @param array $variables
 *   An associative array containing:
 *   - item: An array of image data.
 *   - image_style: An optional image style.
 *   - path: An array containing the link 'path' and link 'options'.
 *
 * @ingroup themeable
 */
function theme_image_url_formatter($variables) {
  $item = $variables['item'];
  $image = array(
    'path' => $item['uri'],
    'alt' => $item['alt'],
  );
  // Do not output an empty 'title' attribute.
  if (drupal_strlen($item['title']) > 0) {
    $image['title'] = $item['title'];
  }
  // Return the URI path.
  if ($variables['url_type'] == 3) {
    return $item['uri'];
  }
  $output = file_create_url($item['uri']);
  if ($variables['image_style']) {
    $image['style_name'] = $variables['image_style'];
    $output = image_style_url($image['style_name'], $item['uri']);
  }
  $output = image_url_formatter_convert_full_url($output, $variables['url_type']);
  if ($variables['path']) {
    $path = $variables['path']['path'];
    $path = image_url_formatter_convert_full_url($path, $variables['url_type']);
    $options = $variables['path']['options'];
    // When displaying an image inside a link, the html option must be TRUE.
    $options['html'] = TRUE;
    $output = l($output, $path, $options);
  }

  return $output;
}

/**
 * Converts a full URL to the choosen format.
 *
 * @param string $url
 *   The full URL to convet.
 * @param constant $format
 *   IMAGE_URL_FORMATTER_RELATIVE_PATH for relative path,
 *   IMAGE_URL_FORMATTER_ABSOLUTE_PATH for absolute path,
 *   IMAGE_URL_FORMATTER_FULL_URL for full URL.
 *
 * @return string
 *   The converted URL.
 */
function image_url_formatter_convert_full_url($url, $format = IMAGE_URL_FORMATTER_FULL_URL) {
  switch ($format) {
    case IMAGE_URL_FORMATTER_RELATIVE_PATH:
      $url = _image_url_formatter_get_relative_file_url($url);
      break;

    case IMAGE_URL_FORMATTER_ABSOLUTE_PATH:
      $url = _image_url_formatter_get_absolute_file_url($url);
      break;
  }

  return $url;
}

/**
 * Returns an absolute url.
 */
function _image_url_formatter_get_absolute_file_url($url) {
  global $base_url;
  if (strpos($url, $base_url) === 0) {
    $url = base_path() . ltrim(str_replace($GLOBALS['base_url'], '', $url), '/');
  }
  return $url;
}

/**
 * Returns a relative url.
 */
function _image_url_formatter_get_relative_file_url($url) {
  $url = _image_url_formatter_get_absolute_file_url($url);
  if ($url[0] == '/') {
    $url = substr($url, 1);
  }
  return $url;
}
