home | career | drupal | java | mac | mysql | perl | php | scala | uml | unix

Drupal example source code file (link.module)

This example Drupal source code file (link.module) is included in the DevDaily.com "Drupal Source Code Warehouse" project. The intent of this project is to help you "Learn Drupal by Example".

PHP - Drupal tags/keywords

array, directory, empty, field, file, function, if, isset, php, return, string, title, url, variable

The link.module Drupal example source code

<?php
// $Id: link.module,v 1.25.2.14 2011/02/07 06:39:47 jcfiala Exp $

/**
 * @file
 * Defines simple link field types.
 */

define('LINK_EXTERNAL', 'external');
define('LINK_INTERNAL', 'internal');
define('LINK_FRONT', 'front');
define('LINK_EMAIL', 'email');
define('LINK_NEWS', 'news');
define('LINK_DOMAINS', 'aero|arpa|asia|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|local');

define('LINK_TARGET_DEFAULT', 'default');
define('LINK_TARGET_NEW_WINDOW', '_blank');
define('LINK_TARGET_TOP', '_top');
define('LINK_TARGET_USER', 'user');

/**
 * Maximum URLs length.
 */
define('LINK_URL_MAX_LENGTH', 2048);

/**
 * Implements hook_field_info().
 */
function link_field_info() {
  return array(
    'link_field' => array(
      'label' => t('Link'),
      'description' => t('Store a title, href, and attributes in the database to assemble a link.'),
      'settings' => array(
        'attributes' => _link_default_attributes(),
        'url' => 0,
        'title' => 'optional',
        'title_value' => '',
        'enable_tokens' => 1,
        'display' => array(
          'url_cutoff' => 80,
        ),
      ),
      'instance_settings' => array(
        'attributes' => _link_default_attributes(),
        'url' => 0,
        'title' => 'optional',
        'title_value' => '',
        'enable_tokens' => 1,
        'display' => array(
          'url_cutoff' => 80,
        ),
      ),
      'default_widget' => 'link_field',
      'default_formatter' => 'default',
    ),
  );
}

/**
 * Implements hook_field_instance_settings_form().
 */
function link_field_instance_settings_form($field, $instance) {
  $form = array(
    '#element_validate' => array('link_field_settings_form_validate'),
  );

  $form['url'] = array(
    '#type' => 'checkbox',
    '#title' => t('Optional URL'),
    '#default_value' => isset($instance['settings']['url']) ? $instance['settings']['url'] : '',
    '#return_value' => 'optional',
    '#description' => t('If checked, the URL field is optional and submitting a title alone will be acceptable. If the URL is omitted, the title will be displayed as plain text.'),
  );

  $title_options = array(
    'optional' => t('Optional Title'),
    'required' => t('Required Title'),
    'value' => t('Static Title'),
    'none' => t('No Title'),
  );

  $form['title'] = array(
    '#type' => 'radios',
    '#title' => t('Link Title'),
    '#default_value' => isset($instance['settings']['title']) ? $instance['settings']['title'] : 'optional',
    '#options' => $title_options,
    '#description' => t('If the link title is optional or required, a field will be displayed to the end user. If the link title is static, the link will always use the same title. If <a href="http://drupal.org/project/token">token module</a> is installed, the static title value may use any other node field as its value. Static and token-based titles may include most inline XHTML tags such as <em>strong</em>, <em>em</em>, <em>img</em>, <em>span</em>, etc.'),
  );

  $form['title_value'] = array(
    '#type' => 'textfield',
    '#title' => t('Static title'),
    '#default_value' => isset($instance['settings']['title_value']) ? $instance['settings']['title_value'] : '',
    '#description' => t('This title will always be used if &ldquo;Static Title&rdquo; is selected above.'),
  );

  if (module_exists('token')) {
    // Add token module replacements fields
    $form['tokens'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#title' => t('Placeholder tokens'),
      '#description' => t("The following placeholder tokens can be used in both paths and titles. When used in a path or title, they will be replaced with the appropriate values."),
    );
    $token_type = array(
      'theme' => 'token_tree',
      'token_types' => array($instance['entity_type']),
      'global_types' => TRUE,
      'click_insert' => TRUE,
      'recursion_limit' => 2,
    );
    $form['tokens']['help'] = array(
      '#type' => 'markup',
      '#markup' => theme('token_tree', $token_type),
    );

    $form['enable_tokens'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow user-entered tokens'),
      '#default_value' => isset($instance['settings']['enable_tokens']) ? $instance['settings']['enable_tokens'] : 1,
      '#description' => t('Checking will allow users to enter tokens in URLs and Titles on the node edit form. This does not affect the field settings on this page.'),
    );
  }

  $form['display'] = array(
    '#tree' => TRUE,
  );
  $form['display']['url_cutoff'] = array(
    '#type' => 'textfield',
    '#title' => t('URL Display Cutoff'),
    '#default_value' => isset($instance['settings']['display']['url_cutoff']) ? $instance['settings']['display']['url_cutoff'] : '80',
    '#description' => t('If the user does not include a title for this link, the URL will be used as the title. When should the link title be trimmed and finished with an elipsis (&hellip;)? Leave blank for no limit.'),
    '#maxlength' => 3,
   '#size' => 3,
  );

  $target_options = array(
    LINK_TARGET_DEFAULT => t('Default (no target attribute)'),
    LINK_TARGET_TOP => t('Open link in window root'),
    LINK_TARGET_NEW_WINDOW => t('Open link in new window'),
    LINK_TARGET_USER => t('Allow the user to choose'),
  );
  $form['attributes'] = array(
    '#tree' => TRUE,
  );
  $form['attributes']['target'] = array(
    '#type' => 'radios',
    '#title' => t('Link Target'),
    '#default_value' => empty($instance['settings']['attributes']['target']) ? LINK_TARGET_DEFAULT : $instance['settings']['attributes']['target'],
    '#options' => $target_options,
  );
  $form['attributes']['rel'] = array(
    '#type' => 'textfield',
    '#title' => t('Rel Attribute'),
    '#description' => t('When output, this link will have this rel attribute. The most common usage is <a href="http://en.wikipedia.org/wiki/Nofollow">rel=&quot;nofollow&quot;</a> which prevents some search engines from spidering entered links.'),
    '#default_value' => empty($instance['settings']['attributes']['rel']) ? '' : $instance['settings']['attributes']['rel'],
    '#field_prefix' => 'rel = "',
    '#field_suffix' => '"',
    '#size' => 20,
  );
  $form['attributes']['class'] = array(
    '#type' => 'textfield',
    '#title' => t('Additional CSS Class'),
    '#description' => t('When output, this link will have have this class attribute. Multiple classes should be separated by spaces.'),
    '#default_value' => empty($instance['settings']['attributes']['class']) ? '' : $instance['settings']['attributes']['class'],
  );
  return $form;
}

/**
 * Validate the field settings form.
 */
function link_field_settings_form_validate($element, &$form_state, $complete_form) {
  if ($form_state['values']['instance']['settings']['title'] === 'value'
      && empty($form_state['values']['instance']['settings']['title_value'])) {
    form_set_error('title_value', t('A default title must be provided if the title is a static value.'));
  }
}

/**
 * Implement hook_field_is_empty().
 */
function link_field_is_empty($item, $field) {
  return empty($item['title']) && empty($item['url']);
}

/**
 * Implements hook_field_load().
 */
function link_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
  foreach ($entities as $id => $entity) {
    foreach ($items[$id] as $delta => $item) {
      $items[$id][$delta]['attributes'] = _link_load($field, $item, $instances[$id]);
    }
  }
}

/**
 * Implements hook_field_validate().
 */
function link_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
  $optional_field_found = FALSE;
  foreach ($items as $delta => $value) {
    _link_validate($items[$delta], $delta, $field, $entity, $instance, $optional_field_found);
  }
}

/**
 * Implements hook_field_presave().
 */
function link_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  foreach ($items as $delta => $value) {
    _link_process($items[$delta], $delta, $field, $entity);
  }
}

/**
 * Implements hook_field_prepare_view().
 */
function link_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
  foreach ($items as $entity_id => $entity_items) {
    foreach ($entity_items as $delta => $value) {
      _link_sanitize($items[$entity_id][$delta], $delta, $field, $instances[$entity_id], $entities[$entity_id]);
    }
  }
}

/**
 * Implements hook_field_widget_info().
 */
function link_field_widget_info() {
  return array(
    'link_field' => array(
      'label' => 'Link',
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 */
function link_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $element += array(
    '#type' => $instance['widget']['type'],
    '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
  );
  return $element;
}

/**
 * Unpacks the item attributes for use.
 */
function _link_load($field, $item, $instance) {
  /*return $item['attributes'] = isset($item['attributes']) ?
                                unserialize($item['attributes']) :
                                $instance['settings']['attributes'];*/
  if (isset($item['attributes'])) {
    return unserialize($item['attributes']);
  }
  else if (isset($instance['settings']['attributes'])) {
    return $instance['settings']['attributes'];
  }
  else {
    return $field['settings']['attributes'];
  }
}

/**
 * Prepares the item attributes and url for storage.
 */
function _link_process(&$item, $delta = 0, $field, $entity) {
  // Trim whitespace from URL.
  $item['url'] = trim($item['url']);

  // if no attributes are set then make sure $item['attributes'] is an empty array - this lets $field['attributes'] override it.
  if (empty($item['attributes'])) {
    $item['attributes'] = array();
  }

  // Serialize the attributes array.
  $item['attributes'] = serialize($item['attributes']);

  // Don't save an invalid default value (e.g. 'http://').
  if ((isset($field['widget']['default_value'][$delta]['url']) && $item['url'] == $field['widget']['default_value'][$delta]['url'])
      && is_object($node)) {
    if (!link_validate_url($item['url'])) {
      unset($item['url']);
    }
  }
}

/**
 * Validates that the link field has been entered properly.
 */
function _link_validate(&$item, $delta, $field, $node, $instance, &$optional_field_found) {
  if ($item['url']
                    && !(isset($instance['default_value'][$delta]['url'])
                        && $item['url'] === $instance['default_value'][$delta]['url']
                        && !$instance['required'])) {
    // Validate the link.
    if (link_validate_url(trim($item['url'])) == FALSE) {
      form_set_error($field['field_name'] .']['. $delta .'][url', t('Not a valid URL.'));
    }
    // Require a title for the link if necessary.
    if ($instance['settings']['title'] == 'required' && strlen(trim($item['title'])) == 0) {
      form_set_error($field['field_name'] .']['. $delta .'][title', t('Titles are required for all links.'));
    }
  }
  // Require a link if we have a title.
  if ($instance['settings']['url'] !== 'optional'
      && strlen(isset($item['title']) ? $item['title'] : NULL) > 0
      && strlen(trim($item['url'])) == 0) {
    form_set_error($field['field_name'] .']['. $delta .'][url', t('You cannot enter a title without a link url.'));
  }
  // In a totally bizzaro case, where URLs and titles are optional but the field is required, ensure there is at least one link.
  if ($instance['settings']['url'] === 'optional'
      && $instance['settings']['title'] === 'optional'
      && (strlen(trim($item['url'])) !== 0 || strlen(trim($item['title'])) !== 0)) {
    $optional_field_found = TRUE;
  }
  // Require entire field
  if ($instance['settings']['url'] === 'optional'
    && $instance['settings']['title'] === 'optional'
    && $instance['required'] == 1
    && !$optional_field_found
    && isset($instance['id'])) {
    form_set_error($instance['field_name'] .'][0][title',
                   t('At least one title or URL must be entered.'));
  }
}

/**
 * Cleanup user-entered values for a link field according to field settings.
 *
 * @param $item
 *   A single link item, usually containing url, title, and attributes.
 * @param $delta
 *   The delta value if this field is one of multiple fields.
 * @param $field
 *   The CCK field definition.
 * @param $node
 *   The node containing this link.
 */
function _link_sanitize(&$item, $delta, &$field, $instance, &$node) {
  // Don't try to process empty links.
  if (empty($item['url']) && empty($item['title'])) {
    return;
  }

  // Replace URL tokens.
  if ($instance['settings']['enable_tokens']) {
    global $user;
    // Load the node if necessary for nodes in views.
    $token_node = isset($node->nid) ? node_load($node->nid) : $node;
    $item['url'] = token_replace($item['url'], array('node' => $token_node));
  }

  $type = link_validate_url($item['url']);
  $url = link_cleanup_url($item['url']);

  // Separate out the anchor if any.
  if (strpos($url, '#') !== FALSE) {
    $item['fragment'] = substr($url, strpos($url, '#') + 1);
    $url = substr($url, 0, strpos($url, '#'));
  }
  // Separate out the query string if any.
  if (strpos($url, '?') !== FALSE) {
    $query = substr($url, strpos($url, '?') + 1);
    parse_str($query, $query_array);
    $item['query'] = $query_array;
    $url = substr($url, 0, strpos($url, '?'));
  }

  // Create a shortened URL for display.
  $display_url = $type == LINK_EMAIL ?
                  str_replace('mailto:', '', $url) :
                  url($url, array('query' => isset($item['query']) ?
                                              $item['query'] :
                                              NULL,
                                  'fragment' => isset($item['fragment']) ?
                                                $item['fragment'] :
                                                NULL,
                                  'absolute' => TRUE));
  if ($instance['settings']['display']['url_cutoff'] && strlen($display_url) > $instance['settings']['display']['url_cutoff']) {
    $display_url = substr($display_url, 0, $instance['settings']['display']['url_cutoff']) ."...";
  }
  $item['display_url'] = $display_url;

  // Use the title defined at the instance level.
  if ($instance['settings']['title'] == 'value' && strlen(trim($instance['settings']['title_value']))) {
    $title = $instance['settings']['title_value'];
  }
  // Use the title defined by the user at the widget level.
  else if (isset($item['title'])) {
    $title = $item['title'];
  }
  else {
    $title = '';
  }

  // Replace tokens.
  if ($title && ($instance['settings']['title'] == 'value' || $instance['settings']['enable_tokens'])) {
    // Load the node if necessary for nodes in views.
    $token_node = isset($node->nid) ? node_load($node->nid) : $node;
    $title = filter_xss(token_replace($title, array('node' => $token_node)),
                        array('b', 'br', 'code', 'em', 'i', 'img', 'span', 'strong', 'sub', 'sup', 'tt', 'u'));
    $item['html'] = TRUE;
  }
  $item['title'] = empty($title) ? $item['display_url'] : $title;

  if (!isset($item['attributes'])) {
    $item['attributes'] = array();
  }

  // Unserialize attributtes array if it has not been unserialized yet.
  if (!is_array($item['attributes'])) {
    $item['attributes'] = (array)unserialize($item['attributes']);
  }

  // Add default attributes.
  if (!is_array($instance['settings']['attributes'])){
    $instance['settings']['attributes'] = _link_default_attributes();
  }
  else {
    $instance['settings']['attributes'] += _link_default_attributes();
  }

  // Merge item attributes with attributes defined at the field level.
  $item['attributes'] += $instance['settings']['attributes'];

  // If user is not allowed to choose target attribute, use default defined at
  // field level.
  if ($instance['settings']['attributes']['target'] != LINK_TARGET_USER) {
    $item['attributes']['target'] = $instance['settings']['attributes']['target'];
  }

  // Remove the target attribute if the default (no target) is selected.
  if (empty($item['attributes']) || $item['attributes']['target'] == LINK_TARGET_DEFAULT) {
    unset($item['attributes']['target']);
  }

  // Remove the rel=nofollow for internal links.
  if ($type != LINK_EXTERNAL && strpos($item['attributes']['rel'], 'nofollow') !== FALSE) {
    $item['attributes']['rel'] = str_replace('nofollow', '', $item['attributes']);
  }

  // Remove empty attributes.
  $item['attributes'] = array_filter($item['attributes']);

  // Sets title to trimmed url if one exists
  // @TODO: Do we need this?  It seems not.
  /*if(!empty($item['display_url']) && empty($item['title'])) {
    $item['title'] = $item['display_url'];
  }
  elseif(!isset($item['title'])) {
    $item['title'] = $item['url'];
  }*/

}

/**
 * Implements hook_theme().
 */
function link_theme() {
  return array(
    /*'link_field_settings' => array(
      'variables' => array('element' => NULL),
    ),*/
    'link_formatter_default' => array(
      'variables' => array('element' => NULL),
    ),
    'link_formatter_plain' => array(
      'variables' => array('element' => NULL),
    ),
    'link_formatter_url' => array(
      'variables' => array('element' => NULL),
    ),
    'link_formatter_short' => array(
      'variables' => array('element' => NULL),
    ),
    'link_formatter_label' => array(
      'variables' => array('element' => NULL),
    ),
    'link_formatter_separate' => array(
      'variables' => array('element' => NULL),
    ),
    'link_field' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * FAPI theme for an individual text elements.
 */
function theme_link_field($vars) {
  drupal_add_css(drupal_get_path('module', 'link') .'/link.css');

  $element = $vars['element'];
  // Prefix single value link fields with the name of the field.
  if (empty($element['#field']['multiple'])) {
    if (isset($element['url']) && !isset($element['title'])) {
      unset($element['url']['#title']);
    }
  }

  $output = '';
  $output .= '<div class="link-field-subrow clearfix">';
  if (isset($element['title'])) {
    $output .= '<div class="link-field-title link-field-column">'. drupal_render($element['title']) .'</div>';
  }
  $output .= '<div class="link-field-url'. (isset($element['title']) ? ' link-field-column' : '') .'">'. drupal_render($element['url']) .'</div>';
  $output .= '</div>';
  if (!empty($element['attributes']['target'])) {
    $output .= '<div class="link-attributes">'. drupal_render($element['attributes']['target']) .'</div>';
  }
  return $output;
}

/**
 * Implements hook_element_info().
 */
function link_element_info() {
  $elements = array();
  $elements['link_field'] =  array(
    '#input' => TRUE,
    '#process' => array('link_field_process'),
    '#theme' => 'link_field',
    '#theme_wrappers' => array('form_element'),
  );
  return $elements;
}

function _link_default_attributes() {
  return array(
    'target' => LINK_TARGET_DEFAULT,
    'class' => '',
    'rel' => '',
  );
}

/**
 * Process the link type element before displaying the field.
 *
 * Build the form element. When creating a form using FAPI #process,
 * note that $element['#value'] is already set.
 *
 * The $fields array is in $complete_form['#field_info'][$element['#field_name']].
 */
function link_field_process($element, $form_state, $complete_form) {
  $settings = &$form_state['field'][$element['#field_name']][$element['#language']]['instance']['settings'];
  $element['url'] = array(
    '#type' => 'textfield',
    '#maxlength' => LINK_URL_MAX_LENGTH,
    '#title' => t('URL'),
    '#required' => ($element['#delta'] == 0 && $settings['url'] !== 'optional') ? $element['#required'] : FALSE,
    '#default_value' => isset($element['#value']['url']) ? $element['#value']['url'] : NULL,
  );
  if ($settings['title'] !== 'none' && $settings['title'] !== 'value') {
    $element['title'] = array(
      '#type' => 'textfield',
      '#maxlength' => '255',
      '#title' => t('Title'),
      '#required' => ($settings['title'] == 'required' && !empty($element['#value']['url'])) ? TRUE : FALSE,
      '#default_value' => isset($element['#value']['title']) ? $element['#value']['title'] : NULL,
    );
  }

  // Initialize field attributes as an array if it is not an array yet.
  if (!is_array($settings['attributes'])) {
    $settings['attributes'] = array();
  }
  // Add default atrributes.
  $settings['attributes'] += _link_default_attributes();
  $attributes = isset($element['#value']['attributes']) ? $element['#value']['attributes'] : $settings['attributes'];
  if (!empty($settings['attributes']['target']) && $settings['attributes']['target'] == LINK_TARGET_USER) {
    $element['attributes']['target'] = array(
      '#type' => 'checkbox',
      '#title' => t('Open URL in a New Window'),
      '#return_value' => LINK_TARGET_NEW_WINDOW,
      '#default_value' => isset($attributes['target']) ? $attributes['target'] : FALSE,
    );
  }
  return $element;
}

/**
 * Implementation of hook_field_formatter_info().
 */
function link_field_formatter_info() {
  return array(
    'default' => array(
      'label' => t('Title, as link (default)'),
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
    'url' => array(
      'label' => t('URL, as link'),
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
    'plain' => array(
      'label' => t('URL, as plain text'),
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
    'short' => array(
      'label' => t('Short, as link with title "Link"'),
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
    'label' => array(
      'label' => t('Label, as link with label as title'),
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
    'separate' => array(
      'label' => t('Separate title and URL'),
      'field types' => array('link_field'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function link_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $elements = array();
  foreach ($items as $delta => $item) {
    $elements[$delta] = array(
      '#markup' => theme('link_formatter_'. $display['type'], array('element' => $item, 'field' => $instance)),
    );
  }
  return $elements;
}

/**
 * Theme function for 'default' text field formatter.
 */
function theme_link_formatter_default($vars) {
  // Display a normal link if both title and URL are available.
  if (!empty($vars['element']['title']) && !empty($vars['element']['url'])) {
    return l($vars['element']['title'], $vars['element']['url'], array('attributes' => $vars['element']['attributes']));
  }
  // If only a title, display the title.
  elseif (!empty($vars['element']['title'])) {
    return check_plain($vars['element']['title']);
  }
  elseif (!empty($vars['element']['url'])) {
    return l($vars['element']['title'], $vars['element']['url'], array('attributes' => $vars['element']['attributes']));
  }
}

/**
 * Theme function for 'plain' text field formatter.
 */
function theme_link_formatter_plain($vars) {
  return empty($vars['element']['url']) ? check_plain($vars['element']['title']) : url($vars['element']['url'], array('attributes' => $vars['element']['attributes']));
}

/**
 * Theme function for 'url' text field formatter.
 */
function theme_link_formatter_url($vars) {
  return $vars['element']['url'] ? l($vars['element']['display_url'], $vars['element']['url'], array('attributes' => $vars['element']['attributes'])) : '';
}

/**
 * Theme function for 'short' text field formatter.
 */
function theme_link_formatter_short($vars) {
  return $vars['element']['url'] ? l(t('Link'), $vars['element']['url'], array('attributes' => $vars['element']['attributes'])) : '';
}

/**
 * Theme function for 'label' text field formatter.
 */
function theme_link_formatter_label($vars) {
  return $vars['element']['url'] ? l($vars['field']['label'], $vars['element']['url'], array('attributes' => $vars['element']['attributes'])) : '';
}

/**
 * Theme function for 'separate' text field formatter.
 */

function theme_link_formatter_separate($vars) {
  $class = empty($vars['element']['attributes']['class']) ? '' : ' '. $vars['element']['attributes']['class'];
  unset($vars['element']['attributes']['class']);
  $title = empty($vars['element']['title']) ? '' : check_plain($vars['element']['title']);

  $output = '';
  $output .= '<div class="link-item '. $class .'">';
  if (!empty($title)) {
    $output .= '<div class="link-title">'. $title .'</div>';
  }
  $output .= '<div class="link-url">'. l($vars['element']['url'], $vars['element']['url'], array('attributes' => $vars['element']['attributes'])) .'</div>';
  $output .= '</div>';
  return $output;
}


function link_token_list($type = 'all') {
  if ($type === 'field' || $type === 'all') {
    $tokens = array();

    $tokens['link']['url'] = t("Link URL");
    $tokens['link']['title'] = t("Link title");
    $tokens['link']['view'] = t("Formatted html link");

    return $tokens;
  }
}

function link_token_values($type, $object = NULL) {
  if ($type === 'field') {
    $item = $object[0];

    $tokens['url'] = $item['url'];
    $tokens['title'] = $item['title'];
    $tokens['view'] = isset($item['view']) ? $item['view'] : '';

    return $tokens;
  }
}

/**
 * Implements hook_views_api().
 */
function link_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'link') .'/views',
  );
}

/**
 * Forms a valid URL if possible from an entered address.
 * Trims whitespace and automatically adds an http:// to addresses without a protocol specified
 *
 * @param string $url
 * @param string $protocol The protocol to be prepended to the url if one is not specified
 */
function link_cleanup_url($url, $protocol = "http") {
  $url = trim($url);
  $type = link_validate_url($url);

  if ($type === LINK_EXTERNAL) {
    // Check if there is no protocol specified.
    $protocol_match = preg_match("/^([a-z0-9][a-z0-9\.\-_]*:\/\/)/i", $url);
    if (empty($protocol_match)) {
      // But should there be? Add an automatic http:// if it starts with a domain name.
      $domain_match = preg_match('/^(([a-z0-9]([a-z0-9\-_]*\.)+)('. LINK_DOMAINS .'|[a-z]{2}))/i', $url);
      if (!empty($domain_match)) {
        $url = $protocol ."://". $url;
      }
    }
  }

  return $url;
}

/**
 * A lenient verification for URLs. Accepts all URLs following RFC 1738 standard
 * for URL formation and all email addresses following the RFC 2368 standard for
 * mailto address formation.
 *
 * @param string $text
 * @return mixed Returns boolean FALSE if the URL is not valid. On success, returns an object with
 * the following attributes: protocol, hostname, ip, and port.
 */
function link_validate_url($text) {
  $LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array(
    "&#x00E6;", // æ
    "&#x00C6;", // Æ
    "&#x00F8;", // ø
    "&#x00D8;", // Ø
    "&#x00E5;", // å
    "&#x00C5;", // Å
    "&#x00E4;", // ä
    "&#x00C4;", // Ä
    "&#x00F6;", // ö
    "&#x00D6;", // Ö
    "&#x00FC;", // ü
    "&#x00DC;", // Ü
    "&#x00D1;", // Ñ
    "&#x00F1;", // ñ
  )), ENT_QUOTES, 'UTF-8');

  $LINK_ICHARS = $LINK_ICHARS_DOMAIN . (string) html_entity_decode(implode("", array(
    "&#x00DF;", // ß
  )), ENT_QUOTES, 'UTF-8');
  $allowed_protocols = variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal'));

  $protocol = '(('. implode("|", $allowed_protocols) .'):\/\/)';
  $authentication = '(([a-z0-9%' . $LINK_ICHARS . ']+(:[a-z0-9%'. $LINK_ICHARS . '!]*)?)?@)';
  $domain = '(([a-z0-9' . $LINK_ICHARS_DOMAIN . ']([a-z0-9'. $LINK_ICHARS_DOMAIN . '\-_\[\]])*)(\.(([a-z0-9' . $LINK_ICHARS_DOMAIN . '\-_\[\]])+\.)*('. LINK_DOMAINS .'|[a-z]{2}))?)';
  $ipv4 = '([0-9]{1,3}(\.[0-9]{1,3}){3})';
  $ipv6 = '([0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7})';
  $port = '(:([0-9]{1,5}))';

  // Pattern specific to external links.
  $external_pattern = '/^'. $protocol .'?'. $authentication .'?('. $domain .'|'. $ipv4 .'|'. $ipv6 .' |localhost)'. $port .'?';

  // Pattern specific to internal links.
  $internal_pattern = "/^([a-z0-9". $LINK_ICHARS ."_\-+\[\]]+)";
  $internal_pattern_file = "/^([a-z0-9". $LINK_ICHARS ."_\-+\[\]\.]+)$/i";

  $directories = "(\/[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'!():;*@\[\]]*)*";
  // Yes, four backslashes == a single backslash.
  $query = "(\/?\?([?a-z0-9". $LINK_ICHARS ."+_|\-\.\/\\\\%=&,$'():;*@\[\]{} ]*))";
  $anchor = "(#[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'():;*@\[\]\/\?]*)";

  // The rest of the path for a standard URL.
  $end = $directories .'?'. $query .'?'. $anchor .'?'.'$/i';

  $message_id = '[^@].*@'. $domain;
  $newsgroup_name = '([0-9a-z+-]*\.)*[0-9a-z+-]*';
  $news_pattern = '/^news:('. $newsgroup_name .'|'. $message_id .')$/i';

  $user = '[a-zA-Z0-9'. $LINK_ICHARS .'_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\'\[\]]+';
  $email_pattern = '/^mailto:'. $user .'@'.'('. $domain .'|'. $ipv4 .'|'. $ipv6 .'|localhost)'. $query .'?$/';

  if (strpos($text, '<front>') === 0) {
    return LINK_FRONT;
  }
  if (in_array('mailto', $allowed_protocols) && preg_match($email_pattern, $text)) {
    return LINK_EMAIL;
  }
  if (in_array('news', $allowed_protocols) && preg_match($news_pattern, $text)) {
    return LINK_NEWS;
  }
  if (preg_match($internal_pattern . $end, $text)) {
    return LINK_INTERNAL;
  }
  if (preg_match($external_pattern . $end, $text)) {
    return LINK_EXTERNAL;
  }
  if (preg_match($internal_pattern_file, $text)) {
    return LINK_INTERNAL;
  }

  return FALSE;
}

/**
 * Implements hook_migrate_field_alter().
 */
function link_content_migrate_field_alter(&$field_value, $instance_value) {
  if ($field_value['type'] == 'link') {
    // need to change the type:
    $field_value['type'] = 'link_field';
  }
}

/**
 * Implements hook_migrate_instance_alter().
 *
 * Widget type also changed to link_field.
 */
function link_content_migrate_instance_alter(&$instance_value, $field_value) {
  if ($instance_value['widget']['module'] == 'link'
      && $instance_value['widget']['type'] == 'link') {
    $instance_value['widget']['type'] = 'link_field';
  }
}

Other Drupal examples (source code examples)

Here is a short list of links related to this Drupal link.module source code file:

new blog posts

"Drupal" is a registered trademark of Dries Buytaert.

my drupal tutorials and examples  

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

Beginning in 2016, a portion of the proceeds from pages under the '/drupal-code-examples/' URI will be donated to charity.