';
if (isset($element['title'])) {
$output .= '
' . drupal_render($element['title']) . '
';
}
$output .= '
'. drupal_render($element['url']) . '
';
$output .= '
';
if (!empty($element['attributes']['target'])) {
$output .= '' . drupal_render($element['attributes']['target']) . '
';
}
if (!empty($element['attributes']['title'])) {
$output .= '' . drupal_render($element['attributes']['title']) . '
';
}
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;
}
/**
* Returns the default attributes and their values.
*/
function _link_default_attributes() {
return array(
'target' => LINK_TARGET_DEFAULT,
'class' => '',
'rel' => '',
);
}
/**
* Processes 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) {
$instance = field_widget_instance($element, $form_state);
$settings = $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' => $settings['title_maxlength'],
'#title' => t('Title'),
'#description' => t('The link title is limited to @maxlength characters maximum.', array('@maxlength' => $settings['title_maxlength'])),
'#required' => ($settings['title'] == 'required' && (($element['#delta'] == 0 && $element['#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 attributes.
$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,
);
}
if (!empty($settings['attributes']['configurable_title']) && $settings['attributes']['configurable_title'] == 1) {
$element['attributes']['title'] = array(
'#type' => 'textfield',
'#title' => t('Link "title" attribute'),
'#default_value' => isset($attributes['title']) ? $attributes['title'] : '',
'#field_prefix' => 'title = "',
'#field_suffix' => '"',
);
}
// If the title field is avaliable or there are field accepts multiple values
// then allow the individual field items display the required asterisk if needed.
if (isset($element['title']) || isset($element['_weight'])) {
// To prevent an extra required indicator, disable the required flag on the
// base element since all the sub-fields are already required if desired.
$element['#required'] = FALSE;
}
return $element;
}
/**
* Implements hook_field_formatter_info().
*/
function link_field_formatter_info() {
return array(
'link_default' => array(
'label' => t('Title, as link (default)'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_title_plain' => array(
'label' => t('Title, as plain text'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_url' => array(
'label' => t('URL, as link'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_plain' => array(
'label' => t('URL, as plain text'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_absolute' => array(
'label' => t('URL, absolute'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_domain' => array(
'label' => t('Domain, as link'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'settings' => array(
'strip_www' => FALSE,
),
),
'link_short' => array(
'label' => t('Short, as link with title "Link"'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_label' => array(
'label' => t('Label, as link with label as title'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
'link_separate' => array(
'label' => t('Separate title and URL'),
'field types' => array('link_field'),
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
);
}
/**
* Implements hook_field_formatter_settings_form().
*/
function link_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$element = array();
if ($display['type'] == 'link_domain') {
$element['strip_www'] = array(
'#title' => t('Strip www. from domain'),
'#type' => 'checkbox',
'#default_value' => $settings['strip_www'],
);
}
return $element;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function link_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
if ($display['type'] == 'link_domain') {
if ($display['settings']['strip_www']) {
return t('Strip www. from domain');
}
else {
return t('Leave www. in domain');
}
}
return '';
}
/**
* 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(
'#theme' => 'link_formatter_' . $display['type'],
'#element' => $item,
'#field' => $instance,
'#display' => $display,
);
}
return $elements;
}
/**
* Formats a link.
*/
function theme_link_formatter_link_default($vars) {
$link_options = $vars['element'];
unset($link_options['title']);
unset($link_options['url']);
if (isset($link_options['attributes']['class'])) {
$link_options['attributes']['class'] = array($link_options['attributes']['class']);
}
// 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'], $link_options);
}
// 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'], $link_options);
}
}
/**
* Formats a link (or its title) as plain text.
*/
function theme_link_formatter_link_plain($vars) {
$link_options = $vars['element'];
if (isset($link_options['title'])) {
unset($link_options['title']);
}
else {
$vars['element']['title'] = '';
}
unset($link_options['url']);
return empty($vars['element']['url']) ? check_plain($vars['element']['title']) : url($vars['element']['url'], $link_options);
}
/**
* Formats a link as an absolute URL
*/
function theme_link_formatter_link_absolute($vars) {
$absolute = array('absolute' => TRUE);
return empty($vars['element']['url']) ? '' : url($vars['element']['url'], $absolute + $vars['element']);
}
/**
* Formats a link using the URL's domain for it's link text.
*/
function theme_link_formatter_link_domain($vars) {
$link_options = $vars['element'];
unset($link_options['title']);
unset($link_options['url']);
$domain = parse_url($vars['element']['display_url'], PHP_URL_HOST);
if (!empty($vars['display']['settings']['strip_www'])) {
$domain = str_replace('www.', '', $domain);
}
return $vars['element']['url'] ? l($domain, $vars['element']['url'], $link_options) : '';
}
/**
* Formats a link's title as plain text.
*/
function theme_link_formatter_link_title_plain($vars) {
return empty($vars['element']['title']) ? '' : check_plain($vars['element']['title']);
}
/**
* Formats a link using an alternate display URL for its link text.
*/
function theme_link_formatter_link_url($vars) {
$link_options = $vars['element'];
unset($link_options['title']);
unset($link_options['url']);
return $vars['element']['url'] ? l($vars['element']['display_url'], $vars['element']['url'], $link_options) : '';
}
/**
* Formats a link using "Link" as the link text.
*/
function theme_link_formatter_link_short($vars) {
$link_options = $vars['element'];
unset($link_options['title']);
unset($link_options['url']);
return $vars['element']['url'] ? l(t('Link'), $vars['element']['url'], $link_options) : '';
}
/**
* Formats a link using the field's label as link text.
*/
function theme_link_formatter_link_label($vars) {
$link_options = $vars['element'];
unset($link_options['title']);
unset($link_options['url']);
return $vars['element']['url'] ? l($vars['field']['label'], $vars['element']['url'], $link_options) : '';
}
/**
* Formats a link as separate title and URL elements.
*/
function theme_link_formatter_link_separate($vars) {
$class = empty($vars['element']['attributes']['class']) ? '' : ' ' . $vars['element']['attributes']['class'];
unset($vars['element']['attributes']['class']);
$link_options = $vars['element'];
unset($link_options['title']);
unset($link_options['url']);
$title = empty($vars['element']['title']) ? '' : check_plain($vars['element']['title']);
/**
* @TODO static html markup looks not very elegant
* needs smarter output solution and an optional title/url seperator
*/
$url_parts = _link_parse_url($vars['element']['url']);
$output = '';
$output .= '';
if (!empty($title)) {
$output .= '
' . $title . '
';
}
$output .= '
' . l($url_parts['url'], $vars['element']['url'], $link_options) . '
';
$output .= '
';
return $output;
}
/**
* Implements hook_token_list().
*/
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.
$LINK_DOMAINS = _link_domains();
$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;
}
/**
* Validates a URL.
*
* Accepts all URLs following RFC 1738 standard for URL formation and all e-mail
* 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 one of
* the LINK_(linktype) constants.
*/
function link_validate_url($text) {
// @TODO Complete letters.
$LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array(
"æ", // æ
"Æ", // Æ
"À", // À
"à", // à
"Á", // Á
"á", // á
"Â", // Â
"â", // â
"å", // å
"Å", // Å
"ä", // ä
"Ä", // Ä
"Ç", // Ç
"ç", // ç
"Ð", // Ð
"ð", // ð
"È", // È
"è", // è
"É", // É
"é", // é
"Ê", // Ê
"ê", // ê
"Ë", // Ë
"ë", // ë
"Î", // Î
"î", // î
"Ï", // Ï
"ï", // ï
"ø", // ø
"Ø", // Ø
"ö", // ö
"Ö", // Ö
"Ô", // Ô
"ô", // ô
"Õ", // Õ
"õ", // õ
"Œ", // Œ
"œ", // œ
"ü", // ü
"Ü", // Ü
"Ù", // Ù
"ù", // ù
"Û", // Û
"û", // û
"Ÿ", // Ÿ
"ÿ", // ÿ
"Ñ", // Ñ
"ñ", // ñ
"þ", // þ
"Þ", // Þ
"ý", // ý
"Ý", // Ý
"¿", // ¿
)), ENT_QUOTES, 'UTF-8');
$LINK_ICHARS = $LINK_ICHARS_DOMAIN . (string) html_entity_decode(implode("", array(
"ß", // ß
)), ENT_QUOTES, 'UTF-8');
$allowed_protocols = variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal'));
$LINK_DOMAINS = _link_domains();
// Starting a parenthesis group with (?: means that it is grouped, but is not captured
$protocol = '((?:' . implode("|", $allowed_protocols) . '):\/\/)';
$authentication = "(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=" . $LINK_ICHARS . "]|%[0-9a-f]{2})+(?::(?:[\w" . $LINK_ICHARS . "\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})*)?)?@)";
$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 . "_\-+\[\]\. \/\(\)][a-z0-9" . $LINK_ICHARS . "_\-+\[\]\. \(\)][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, '