向 Drupal 7 节点摘要添加 WISIWYG 支持
我经常在项目中被问到一个简单的请求,而问题的解决方案有时比我原先想象的要复杂。这些问题之一是将WYSIWYG编辑器添加到节点编辑表单上的汇总字段。没有一种简单的方法可以做到这一点,但有可能得到一个好的解决方案。
使用hook_form_alter()钩子我们可以拦截和更改节点编辑表单,将摘要元素的类型从textarea更改为text_format元素。为了使表单的WYSIWYG组件正常工作,我们还需要向表单元素添加格式。出于本示例的目的,我创建了一个名为wysiwyg_summary的模块,因此该挂钩称为wysiwyg_summary_form_alter().
function wysiwyg_summary_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'page_node_form' && isset($form['nid']) && isset($form['body'])) { $form['body'][$form['language']['#value']][0]['summary']['#format'] = 'filtered_html'; $form['body'][$form['language']['#value']][0]['summary']['#type'] = 'text_format'; } }
这似乎工作正常,但我注意到的第一件事是单击“显示摘要”对文本的某些元素有一些奇怪的影响,添加了多个“隐藏摘要”标签。事实证明,问题的罪魁祸首是text.js来自节点字段文本模块(位于/modules/field/modules/text/text.js)的文件。此JavaScript文件包含在节点表单中,需要稍微更新以允许编辑摘要表单元素中的差异。我们需要做的就是改变这个find()函数,让它只找到父元素的第一个标签,而不是每个标签。这是完整的新文件。
(function ($) { /** * Auto-hide summary textarea if empty and show hide and unhide links. */ Drupal.behaviors.textSummary = { attach: function (context, settings) { $('.text-summary', context).once('text-summary', function () { var $widget = $(this).closest('div.field-type-text-with-summary'); var $summaries = $widget.find('div.text-summary-wrapper'); $summaries.once('text-summary-wrapper').each(function(index) { var $summary = $(this); var $summaryLabel = $summary.find('label:first'); var $full = $widget.find('.text-full').eq(index).closest('.form-item'); var $fullLabel = $full.find('label:first'); //当字段基数为时创建占位符标签 //无限制或大于1。 if ($fullLabel.length == 0) { $fullLabel = $('').prependTo($full); } //设置编辑/隐藏摘要链接。 var $link = $('(' + Drupal.t('Hide summary') + ')').toggle( function () { $summary.hide(); $(this).find('a').html(Drupal.t('Edit summary')).end().appendTo($fullLabel); return false; }, function () { $summary.show(); $(this).find('a').html(Drupal.t('Hide summary')).end().appendTo($summaryLabel); return false; } ).appendTo($summaryLabel); //如果未设置汇总,则隐藏汇总字段。 if ($(this).find('.text-summary').val() == '') { $link.click(); } return; }); }); } }; })(jQuery);
要将其添加到节点表单中的原始位置,我们需要更改汇总字段的附加属性,从而替换现有文件。这是更新的代码。
function wysiwyg_summary_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'page_node_form' && isset($form['nid']) && isset($form['body'])) { $form['body'][$form['language']['#value']][0]['summary']['#format'] = 'filtered_html'; $form['body'][$form['language']['#value']][0]['summary']['#type'] = 'text_format'; $form['body'][$form['language']['#value']][0]['summary']['#attached']['js'] = array(drupal_get_path('module', 'wysiwyg_summary') . '/text.js'); } }
最后一步是允许保存来自汇总元素的数据的新结构。最好的方法是使用提交函数将数据转换回Drupal期望的格式。首先要做的是将提交钩子添加到wysiwyg_summary_form_alter().我们在array_unshift()这里使用该函数,以便在任何其他提交函数(特别是核心函数)之前调用提交函数。
/** * Implements hook_form_alter(). */ function wysiwyg_summary_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'page_node_form' && isset($form['nid']) && isset($form['body'])) { $form['body'][$form['language']['#value']][0]['summary']['#format'] = 'filtered_html'; $form['body'][$form['language']['#value']][0]['summary']['#type'] = 'text_format'; $form['body'][$form['language']['#value']][0]['summary']['#attached']['js'] = array(drupal_get_path('module', 'wysiwyg_summary') . '/text.js'); array_unshift($form['#submit'], 'wysiwyg_summary_form_alter_summary_submit'); } }
submit函数的工作是将值从格式摘要元素更改为非格式摘要元素。这里要考虑的一件重要事情是,虽然此文本是使用过滤文本元素输入的,但不会使用任何特定文本格式保存或打印。因此,这意味着将打印输入的任何文本,包括任何恶意脚本。为了解决这个问题,我们可以通过filter_xss()函数传递输入的文本来消除这些问题中的任何一个。我们在这里允许通过的标签足以获得对文本中粗体和链接的基本支持,这就是原始请求的全部内容。
/** * Submit function defined by wysiwyg_summary_form_alter(). */ function wysiwyg_summary_form_alter_summary_submit($form, &$form_state) { $allowed_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'p'); if (isset($form_state['input']['body'][$form['language']['#value']][0]['summary']['value'])) { $form_state['input']['body'][$form['language']['#value']][0]['summary'] = filter_xss($form_state['input']['body'][$form['language']['#value']][0]['summary']['value'], $allowed_tags); } if (isset($form_state['values']['body'][$form['language']['#value']][0]['summary']['value'])) { $form_state['values']['body'][$form['language']['#value']][0]['summary'] = filter_xss($form_state['values']['body'][$form['language']['#value']][0]['summary']['value'], $allowed_tags); } }
有了这个模块,汇总字段现在有部分WYSIWYG支持。唯一真正的问题是它根本不保存或更新过滤器格式,因此您无法完全控制预告片内容的处理方式。为了防止用户对过滤器格式部分存在但不可用这一事实感到困惑,使用CSS隐藏格式部分可能是个好主意。所需要的只是放置一个display:none;关于IDedit-body-und-0-summary-format的规则。
2012年1月10日更新:或者,check_markup()如果该filter_xss()功能过于严格,您可以使用该功能。使用的好处check_markup()是它与您的文本过滤器相关联(在这种情况下它使用'filtered_html'),因此可以让您更好地控制文本发生的情况。