5 * Defines simple link field types.
9 * Implements hook_help().
11 function link_help($path, $arg) {
13 case
'admin/help#link':
15 $output .
= '<h3>' .
t('About') .
'</h3>';
16 $output .
= '<p>' .
t('The Link module defines a simple link field type for the Field module. Links are external URLs, can have an optional title for each link, and they can be formatted when displayed. See the <a href="@field-help">Field module help page</a> for more information about fields.', array('@field-help' => url('admin/help/field'))) .
'</p>';
22 * Implements hook_field_info().
24 function link_field_info() {
25 $types['link'] = array(
27 'description' => t('Stores a URL string, optional varchar title, and optional blob of attributes to assemble a link.'),
28 'instance_settings' => array(
29 'title' => DRUPAL_OPTIONAL
,
31 'default_widget' => 'link_default',
32 'default_formatter' => 'link',
38 * Implements hook_field_instance_settings_form().
40 function link_field_instance_settings_form($field, $instance) {
41 $form['title'] = array(
43 '#title' => t('Allow link title'),
44 '#default_value' => isset($instance['settings']['title']) ?
$instance['settings']['title'] : DRUPAL_OPTIONAL
,
46 DRUPAL_DISABLED
=> t('Disabled'),
47 DRUPAL_OPTIONAL
=> t('Optional'),
48 DRUPAL_REQUIRED
=> t('Required'),
55 * Implements hook_field_load().
57 function link_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
58 foreach ($entities as
$id => $entity) {
59 foreach ($items[$id] as
$delta => &$item) {
60 // Unserialize the attributes into an array. The value stored in the
61 // field data should either be NULL or a non-empty serialized array.
62 if (empty($item['attributes'])) {
63 $item['attributes'] = array();
66 $item['attributes'] = unserialize($item['attributes']);
73 * Implements hook_field_is_empty().
75 function link_field_is_empty($item, $field) {
76 return !isset($item['url']) || $item['url'] === '';
80 * Implements hook_field_presave().
82 function link_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
83 foreach ($items as
$delta => &$item) {
84 // Trim any spaces around the URL and title.
85 $item['url'] = trim($item['url']);
86 $item['title'] = trim($item['title']);
88 // Serialize the attributes array.
89 $item['attributes'] = !empty($item['attributes']) ?
serialize($item['attributes']) : NULL
;
94 * Implements hook_field_widget_info().
96 function link_field_widget_info() {
97 $widgets['link_default'] = array(
99 'field types' => array('link'),
105 * Implements hook_field_widget_form().
107 function link_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
108 $settings = $instance['settings'];
110 $element['url'] = array(
112 '#title' => t('URL'),
113 '#default_value' => isset($items[$delta]['url']) ?
$items[$delta]['url'] : NULL
,
114 '#maxlength' => 2048,
115 '#required' => $element['#required'],
117 $element['title'] = array(
118 '#type' => 'textfield',
119 '#title' => t('Title'),
120 '#default_value' => isset($items[$delta]['title']) ?
$items[$delta]['title'] : NULL
,
122 '#access' => $settings['title'] != DRUPAL_DISABLED
,
124 // Post-process the title field to make it conditionally required if URL is
125 // non-empty. Omit the validation on the field edit form, since the field
126 // settings cannot be saved otherwise.
127 $is_field_edit_form = ($element['#entity'] === NULL
);
128 if (!$is_field_edit_form && $settings['title'] == DRUPAL_REQUIRED
) {
129 $element['#element_validate'][] = 'link_field_widget_validate_title';
132 // Exposing the attributes array in the widget is left for alternate and more
133 // advanced field widgets.
134 $element['attributes'] = array(
137 '#value' => !empty($items[$delta]['attributes']) ?
$items[$delta]['attributes'] : array(),
138 '#attributes' => array('class' => array('link-field-widget-attributes')),
145 * Form element validation handler for link_field_widget_form().
147 * Conditionally requires the link title if a URL value was filled in.
149 function link_field_widget_validate_title(&$element, &$form_state, $form) {
150 if ($element['url']['#value'] !== '' && $element['title']['#value'] === '') {
151 $element['title']['#required'] = TRUE
;
152 form_error($element['title'], t('!name field is required.', array('!name' => $element['title']['#title'])));
157 * Implements hook_field_prepare_view().
159 function link_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
160 foreach ($entities as
$id => $entity) {
161 foreach ($items[$id] as
$delta => &$item) {
162 // Split out the link into the parts required for url(): path and options.
163 $parsed = drupal_parse_url($item['url']);
164 $item['path'] = $parsed['path'];
165 $item['options'] = array(
166 'query' => $parsed['query'],
167 'fragment' => $parsed['fragment'],
168 'attributes' => &$item['attributes'],
175 * Implements hook_field_formatter_info().
177 function link_field_formatter_info() {
178 $formatters['link'] = array(
179 'label' => t('Link'),
180 'field types' => array('link'),
186 'url_plain' => FALSE
,
189 // @todo Merge into 'link' formatter once there is a #type like 'item' that
190 // can render a compound label and content outside of a form context.
191 $formatters['link_separate'] = array(
192 'label' => t('Separate title and URL'),
193 'field types' => array('link'),
204 * Implements hook_field_formatter_settings_form().
206 function link_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
207 $display = $instance['display'][$view_mode];
208 $settings = $display['settings'];
210 $element['trim_length'] = array(
212 '#title' => t('Trim link text length'),
213 '#field_suffix' => t('characters'),
214 '#default_value' => $settings['trim_length'],
216 '#description' => t('Leave blank to allow unlimited link text lengths.'),
218 $element['url_only'] = array(
219 '#type' => 'checkbox',
220 '#title' => t('URL only'),
221 '#default_value' => $settings['url_only'],
222 '#access' => $display['type'] == 'link',
224 $element['url_plain'] = array(
225 '#type' => 'checkbox',
226 '#title' => t('Show URL as plain text'),
227 '#default_value' => $settings['url_plain'],
228 '#access' => $display['type'] == 'link',
231 ':input[name*="url_only"]' => array('checked' => TRUE
),
235 $element['rel'] = array(
236 '#type' => 'checkbox',
237 '#title' => t('Add rel="nofollow" to links'),
238 '#return_value' => 'nofollow',
239 '#default_value' => $settings['nofollow'],
241 $element['target'] = array(
242 '#type' => 'checkbox',
243 '#title' => t('Open link in new window'),
244 '#return_value' => '_blank',
245 '#default_value' => $settings['target'],
252 * Implements hook_field_formatter_settings_form().
254 function link_field_formatter_settings_summary($field, $instance, $view_mode) {
255 $display = $instance['display'][$view_mode];
256 $settings = $display['settings'];
260 if (!empty($settings['trim_length'])) {
261 $summary[] = t('Link text trimmed to @limit characters', array('@limit' => $settings['trim_length']));
264 $summary[] = t('Link text not trimmed');
266 if (!empty($settings['url_only'])) {
267 if (!empty($settings['url_plain'])) {
268 $summary[] = t('Show URL only as plain-text');
271 $summary[] = t('Show URL only');
274 if (!empty($settings['rel'])) {
275 $summary[] = t('Add rel="@rel"', array('@rel' => $settings['rel']));
277 if (!empty($settings['target'])) {
278 $summary[] = t('Open link in new window');
281 return implode('<br />', $summary);
285 * Implements hook_field_formatter_prepare_view().
287 function link_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
288 foreach ($entities as
$id => $entity) {
289 $settings = $displays[$id]['settings'];
291 foreach ($items[$id] as
$delta => &$item) {
292 // Add optional 'rel' attribute to link options.
293 if (!empty($settings['rel'])) {
294 $item['options']['attributes']['rel'] = $settings['rel'];
296 // Add optional 'target' attribute to link options.
297 if (!empty($settings['target'])) {
298 $item['options']['attributes']['target'] = $settings['target'];
305 * Implements hook_field_formatter_view().
307 function link_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
309 $settings = $display['settings'];
311 foreach ($items as
$delta => $item) {
312 // By default use the full URL as the link title.
313 $link_title = $item['url'];
315 // If the title field value is available, use it for the link title.
316 if (empty($settings['url_only']) && !empty($item['title'])) {
317 // Unsanitizied token replacement here because $options['html'] is FALSE
318 // by default in theme_link().
319 $link_title = token_replace($item['title'], array($entity_type => $entity), array('sanitize' => FALSE
, 'clear' => TRUE
));
322 // Trim the link title to the desired length.
323 if (!empty($settings['trim_length'])) {
324 $link_title = truncate_utf8($link_title, $settings['trim_length'], FALSE
, TRUE
);
327 if ($display['type'] == 'link') {
328 if (!empty($settings['url_only']) && !empty($settings['url_plain'])) {
329 $element[$delta] = array(
331 '#markup' => check_plain($link_title),
335 $element[$delta] = array(
337 '#title' => $link_title,
338 '#href' => $item['path'],
339 '#options' => $item['options'],
343 elseif ($display['type'] == 'link_separate') {
344 // The link_separate formatter has two titles; the link title (as in the
345 // field values) and the URL itself. If there is no title value,
346 // $link_title defaults to the URL, so it needs to be unset.
347 // The URL title may need to be trimmed as well.
348 if (empty($item['title'])) {
351 $url_title = $item['url'];
352 if (!empty($settings['trim_length'])) {
353 $url_title = truncate_utf8($item['url'], $settings['trim_length'], FALSE
, TRUE
);
355 $element[$delta] = array(
356 '#theme' => 'link_formatter_link_separate',
357 '#title' => $link_title,
358 '#url_title' => $url_title,
359 '#href' => $item['path'],
360 '#options' => $item['options'],
368 * Implements hook_theme().
370 function link_theme() {
372 'link_formatter_link_separate' => array(
373 'variables' => array('title' => NULL
, 'url_title' => NULL
, 'href' => NULL
, 'options' => array()),
379 * Formats a link as separate title and URL elements.
381 function theme_link_formatter_link_separate($vars) {
383 $output .
= '<div class="link-item">';
384 if (!empty($vars['title'])) {
385 $output .
= '<div class="link-title">' .
check_plain($vars['title']) .
'</div>';
387 $output .
= '<div class="link-url">' .
l($vars['url_title'], $vars['href'], $vars['options']) .
'</div>';