16 为已有字段定制格式器

作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com

 

    有时候,一个字段模块自己提供的格式器,可能会出现不够用的情况,比如说图片字段,在Drupal7里面,它的格式器可以用来显示原始图片、各种缩略图,但是无法显示图片的链接。如果使用views模块的时候,想输出图片字段的URL,默认是不可能的,当然我们可以通过定制views的模板文件,来输出图片的URL。如果我们能够为图片提供一个URL路径格式器,就可以解决上述的问题了。

 

    是的,在drupal.org上就存在着这样的一个第三方模块“Image URL Formatter”,专门来解决这个问题的,这个项目地址是http://drupal.org/project/image_url_formatter我们来学习一下这个模块,这个模块的代码大部分是从image模块中直接拷贝过来的。

 

/**

 * 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'),

      'settings' => array('image_style' => '', 'image_link' => ''),

    ),

  );

 

  return $formatters;

}

    我们在这里为image字段定义了一个新的格式器“Image URL”,顾名思义,它就是用来输出图片的URL路径的。

 

/**

 * 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'];

 

  $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;

}

    这里的定义和核心image模块中的对应实现完全一致。我们创建一个节点类型,并为其添加图片字段,然后启用这个模块,在管理显示页面,假定我们选择了Image URL作为显示格式,如图所示: 

 

图片1.png 

                        图片在管理显示页面的对应项

 

     当我们点击最右边的配置按钮时,就会出现更多的配置选项,如图所示:

图片2.png 

                       格式器自带的设置项

     上述代码就对应于右边的两个配置项。这下我们明白了钩子hook_field_formatter_settings_form是用来做什么的。在这个钩子里面,API函数image_style_options值得学习一下,它用来获取图片的样式选项。

 

/**

 * 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();

 

  $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);

}

    上述代码就对应于图片字段,最右边配置按钮前面的那段描述,如图所示:

 

 

         格式器具体配置的描述

     这个钩子hook_field_formatter_settings_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(),

          );

        }

    //debug($item);

        $element[$delta] = array(

          '#theme' => 'image_url_formatter',

          '#item' => $item,

          '#image_style' => $display['settings']['image_style'],

          '#path' => isset($uri) ? $uri : '',

        );

      }

 

      break;

 

  }

 

  return $element;

}

   在这段代码中,我们返回了图片的呈现数组,在这个呈现数组的每个delta项中,对应的主题函数替换为了theme_image_url_formatter,而不是image模块里面的theme_image_formatter。这里面,API函数file_create_url用来把uri转换为URLuri就是文件在Drupal里面存储的路径信息,但是这种信息,都是这种形式的“public://img/my123.jpg”,我们需要使用这个函数将其转换一下。

/**

 * Implements hook_theme().

 */

function image_url_formatter_theme() {

  return array(

    'image_url_formatter' => array(

      'variables' => array(

        'item' => NULL, 

'path' => NULL, 

'image_style' => NULL,

      ),

    ),

  );

}

 

/**

 * Returns HTML for an image url field formatter.

 *

 * @param $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'];

  }

  $output = file_create_url($item['uri']);

  if ($variables['image_style']) {

//debug($image);

    $image['style_name'] = $variables['image_style'];

$output = image_style_url($image['style_name'], $item['uri']);

  }

  if ($variables['path']) {

    $path = $variables['path']['path'];

    $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;

}

 

     在这个主题函数中,我们返回的是图片的URL,而不是带有img标签的图片了。整个模块,全部都是复制拷贝image模块的代码,只有这里在逻辑上作了修改。image_style_url用来获取图片特定样式下对应图片的URL的。有时候,我们会用到这个函数。

 

     我们看到,为一个已有的字段定义一个新的格式器,并不麻烦,而且很多代码都可以从原有模块中复制过来。采用这种方式的好处是,这个格式器定义好了以后,很多人都可以用,虽然定义的时候稍微麻烦了一点,但是以后会方便很多,送人玫瑰,手留余香。

 


Drupal版本: