editor.filters.inc in Editor 7
Filter hook implementations and callbacks.
File
includes/editor.filters.incView source
<?php
/**
* @file
* Filter hook implementations and callbacks.
*/
/**
* Implements hook_filter_format_insert().
*/
function editor_filter_format_insert($format) {
_editor_format_save($format);
}
/**
* Implements hook_filter_format_update().
*/
function editor_filter_format_update($format) {
_editor_format_save($format);
}
/**
* Helper function to save editor information on text format insert/update.
*
* @param object $format
* An object representing the text format.
*/
function _editor_format_save($format) {
if (!isset($format->editor)) {
$format->editor = '';
}
if (!isset($format->editor_settings)) {
$format->editor_settings = array();
}
// Add 'support' for features.module which will store editor settings as a
// serialized array since it gets its information from filter_format_load()
// and filter_formats() which are hard-coded to ensure that the standard
// filter settings are serialized but cannot be altered to do the same for
// editor settings.
// @todo Remove this when we can ensure that editor setting are unserialized.
$editor_settings = $format->editor_settings;
// Unserialize the editor settings when necessary. This prevents the editor
// settings from being serialized twice.
if ($editor_settings == serialize(false) || @unserialize($editor_settings) !== false) {
$format->editor_settings = unserialize($editor_settings);
}
// Insert or update the text format.
db_merge('filter_format')
->key(array(
'format' => $format->format,
))
->fields(array(
'editor' => $format->editor,
'editor_settings' => serialize($format->editor_settings),
))
->execute();
}
/**
* Implements hook_filter_info().
*/
function editor_filter_info() {
$filters['editor_caption'] = array(
'title' => t('Convert image captions to figure and figcaption elements'),
'process callback' => '_editor_caption',
'tips callback' => '_editor_caption_tips',
'weight' => 4,
);
$filters['editor_align'] = array(
'title' => t('Align images'),
'process callback' => '_editor_align',
'tips callback' => '_editor_align_tips',
'weight' => 5,
);
// Assigns filter types for the Quick Edit module.
if (module_exists('quickedit')) {
$filters['editor_caption']['type'] = FILTER_TYPE_TRANSFORM_REVERSIBLE;
$filters['editor_align']['type'] = FILTER_TYPE_TRANSFORM_REVERSIBLE;
}
return $filters;
}
/**
* Implements callback_filter_process().
*
* Replace img data-caption attributes with figure and figcaption elements.
*/
function _editor_caption($text) {
$result = $text;
if (stristr($text, 'data-caption') !== FALSE) {
// Load the text as a DOM object for manipulation.
$dom = filter_dom_load($text);
$xpath = new DOMXPath($dom);
foreach ($xpath
->query('//*[@data-caption]') as $node) {
// Read the data-caption attribute's value, then delete it.
$caption = $node
->getAttribute('data-caption');
$node
->removeAttribute('data-caption');
// Sanitize caption: decode HTML encoding, limit allowed HTML tags; only
// allow inline tags that are allowed by default, plus <br>.
$caption = filter_xss($caption, array(
'a',
'em',
'strong',
'cite',
'code',
'br',
));
// The caption must be non-empty.
if (drupal_strlen($caption) === 0) {
continue;
}
// Given the updated node and caption: re-render it with a caption, but
// bubble up the value of the class attribute of the captioned element,
// this allows it to collaborate with e.g. the filter_align filter.
$attributes = array();
$tag = $node->tagName;
$classes = $node
->getAttribute('class');
if ($classes) {
$attributes['class'] = explode(' ', $classes);
}
$attributes['class'][] = 'caption';
$attributes['class'][] = 'caption-' . $node->tagName;
$node
->removeAttribute('class');
$node = $node->parentNode->tagName === 'a' ? $node->parentNode : $node;
$theme_parameters = array(
'item' => $node->ownerDocument
->saveHTML($node),
'tag' => $tag,
'caption' => $caption,
'attributes' => $attributes,
);
$editor_caption = theme('editor_caption', $theme_parameters);
// Load the altered HTML into a new DOMDocument and retrieve the element.
$updated_node = filter_dom_load($editor_caption)
->getElementsByTagName('body')
->item(0)->firstChild;
// Import the updated node from the new DOMDocument into the original
// one, importing also the child nodes of the updated node.
$updated_node = $dom
->importNode($updated_node, TRUE);
// Finally, replace the original node with the new node.
$node->parentNode
->replaceChild($updated_node, $node);
}
$result = filter_dom_serialize($dom);
}
return $result;
}
/**
* Implements callback_filter_tips().
*
* Provides help for the caption filter.
*/
function _editor_caption_tips($filter, $format, $long = FALSE) {
if ($long) {
return t('
<p>You can caption images, videos, blockquotes, and so on. Examples:</p>
<ul>
<li><code><img src="" data-caption="This is a caption" /></code></li>
<li><code><video src="" data-caption="The Drupal Dance" /></code></li>
<li><code><blockquote data-caption="Dries Buytaert">Drupal is awesome!</blockquote></code></li>
<li><code><code data-caption="Hello world in JavaScript.">alert("Hello world!");</code></code></li>
</ul>');
}
else {
return t('You can caption images (<code>data-caption="Text"</code>), but also videos, blockquotes, and so on.');
}
}
/**
* Implements callback_filter_process().
*
* Uses a data-align attribute on <img> tags to align images.
*/
function _editor_align($text) {
$result = $text;
if (stristr($text, 'data-align') !== FALSE) {
$dom = filter_dom_load($text);
$xpath = new DOMXPath($dom);
foreach ($xpath
->query('//*[@data-align]') as $node) {
// Read the data-align attribute's value, then delete it.
$align = $node
->getAttribute('data-align');
$node
->removeAttribute('data-align');
// If one of the allowed alignments, add the corresponding class.
if (in_array($align, array(
'left',
'center',
'right',
))) {
$classes = $node
->getAttribute('class');
$classes = strlen($classes) > 0 ? explode(' ', $classes) : array();
$classes[] = 'align-' . $align;
$node
->setAttribute('class', implode(' ', $classes));
}
}
$result = filter_dom_serialize($dom);
}
return $result;
}
/**
* Implements callback_filter_tips().
*
* Provides help for the align filter.
*/
function _editor_align_tips($filter, $format, $long = FALSE) {
if ($long) {
return t('
<p>You can align images, videos, blockquotes and so on to the left, right or center. Examples:</p>
<ul>
<li>Align an image to the left: <code><img src="" data-align="left" /></code></li>
<li>Align an image to the center: <code><img src="" data-align="center" /></code></li>
<li>Align an image to the right: <code><img src="" data-align="right" /></code></li>
<li>… and you can apply this to other elements as well: <code><video src="" data-align="center" /></code></li>
</ul>');
}
else {
return t('You can align images (<code>data-align="center"</code>), but also videos, blockquotes, and so on.');
}
}
/**
* Implements hook_filter_info_alter().
*/
function editor_filter_info_alter(&$info) {
// Add an allowed HTML callback to the core 'filter_html' filter which enables
// it to specify a whitelist of approved HTML tags/attributes.
if (isset($info['filter_html'])) {
$info['filter_html']['allowed html callback'] = '_editor_html_allowed_html';
$info['filter_html']['settings callback'] = '_editor_html_settings';
}
// Add a JS settings callback to the core 'filter_url' filter which makes its
// URL length restrictions available as JS settings.
if (isset($info['filter_url'])) {
$info['filter_url']['js settings callback'] = '_editor_url_js_settings';
}
}
/**
* Implements callback_filter_allowed_html().
*/
function _editor_html_allowed_html($filter, $format) {
// This example is pulled from "filter_html" filter provided by core.
$restrictions = array(
'allowed' => array(),
);
$tags = preg_split('/\\s+|<|>/', $filter->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY);
// List the allowed HTML tags.
foreach ($tags as $tag) {
$restrictions['allowed'][$tag] = TRUE;
}
// The 'style' and 'on*' ('onClick' etc.) attributes are always forbidden.
$restrictions['allowed']['*'] = array(
'style' => FALSE,
'on*' => FALSE,
);
return $restrictions;
}
/**
* Implements callback_filter_settings().
*
* Filter settings callback for the HTML content filter.
*/
function _editor_html_settings($form, $form_state, $filter, $format, $defaults = array(), $filters = array()) {
$filter->settings += $defaults;
$settings['#attached']['library'][] = array(
'filter',
'filter.filtered_html.admin',
);
$settings['allowed_html'] = array(
'#type' => 'textfield',
'#title' => t('Allowed HTML tags'),
'#default_value' => $filter->settings['allowed_html'],
'#maxlength' => 2048,
'#description' => t('A list of HTML tags that can be used. JavaScript event attributes, JavaScript URLs, and CSS are always stripped.'),
);
$settings['filter_html_help'] = array(
'#type' => 'checkbox',
'#title' => t('Display basic HTML help in long filter tips'),
'#default_value' => $filter->settings['filter_html_help'],
);
$settings['filter_html_nofollow'] = array(
'#type' => 'checkbox',
'#title' => t('Add rel="nofollow" to all links'),
'#default_value' => $filter->settings['filter_html_nofollow'],
);
return $settings;
}
/**
* Implements callback_filter_js_settings().
*
* Filter URL JS settings callback: return settings for JavaScript.
*/
function _editor_url_js_settings($filter, $format) {
return array(
'filterUrlLength' => $filter->settings['filter_url_length'],
);
}
Functions
Name | Description |
---|---|
editor_filter_format_insert | Implements hook_filter_format_insert(). |
editor_filter_format_update | Implements hook_filter_format_update(). |
editor_filter_info | Implements hook_filter_info(). |
editor_filter_info_alter | Implements hook_filter_info_alter(). |
_editor_align | Implements callback_filter_process(). |
_editor_align_tips | Implements callback_filter_tips(). |
_editor_caption | Implements callback_filter_process(). |
_editor_caption_tips | Implements callback_filter_tips(). |
_editor_format_save | Helper function to save editor information on text format insert/update. |
_editor_html_allowed_html | Implements callback_filter_allowed_html(). |
_editor_html_settings | Implements callback_filter_settings(). |
_editor_url_js_settings | Implements callback_filter_js_settings(). |