caption_filter.module in Caption Filter 6
Same filename and directory in other branches
Provides a very basic caption filter for input formats
File
caption_filter.moduleView source
<?php
/**
* @file
* caption_filter.module
*
* Provides a very basic caption filter for input formats
*/
/**
* Implementation of hook_init().
*/
function caption_filter_init() {
$path = drupal_get_path('module', 'caption_filter');
drupal_add_css($path . '/caption-filter.css');
drupal_add_js($path . '/js/caption-filter.js');
}
/**
* Implementation of hook_filter().
*/
function caption_filter_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'list':
return array(
0 => t('Caption filter'),
);
case 'description':
return t('Converts [caption] tags and allows image alignment.');
case 'process':
return caption_filter_process_filter($text, $format);
default:
return $text;
}
}
/**
* Implementation of hook_filter_tips().
*/
function caption_filter_filter_tips($delta, $format, $long = FALSE) {
if ($long) {
return t('
<p><strong>Caption Filter</strong></p>
<p>You may wrap images or embeds with a caption using the code <code>[caption]IMAGE caption[/caption]</code>.</p>
<p>Examples:</p>
<ul>
<li>Single Image:<br /><code>[caption]<img src="" />This is a caption[/caption]</code></li>
<li>Align the video:<br /><code>[caption align=right]<img src="" />This is another caption[/caption]</code></li>
</ul>');
}
else {
return check_plain(t('Captions may be specified with [caption]<img src="example.png">Image caption[/caption]. Items can be aligned with [caption align=left].'));
}
}
/**
* Filter process callback. Replace the [caption] tags with HTML.
*/
function caption_filter_process_filter($text, $format = -1) {
// Prevent useless processing if there are no caption tags at all.
if (stristr($text, '[caption') !== FALSE) {
$pattern = "/(\\[caption([^\\]]*)\\])(.*?)(\\[\\/caption\\])/";
$text = preg_replace_callback($pattern, '_caption_filter_replace', $text);
}
return $text;
}
/**
* Callback for preg_replace_callback() in caption_filter_process_filter().
*
* This function actually does the work of replacing each [caption] tag with
* HTML output.
*/
function _caption_filter_replace($matches) {
$caption_attributes = _caption_filter_tag_attributes($matches[2]);
$item = $matches[3];
$width = _caption_filter_get_width($item);
$align = isset($caption_attributes['align']) ? $caption_attributes['align'] : 'center';
$caption = isset($caption_attributes['caption']) ? $caption_attributes['caption'] : '';
// Remove "align" from the start of the alignment if needed. WordPress
// commonly uses align="alignright" for example.
if (strpos($align, 'align') === 0) {
$align = substr($align, 5);
}
return '<div class="caption caption-' . $align . '"><div class="caption-width-container" style="width: ' . $width . ';"><div class="caption-inner">' . $item . $caption . '</div></div></div>';
}
/**
* Determine the width of the img/object that is being captioned.
*/
function _caption_filter_get_width($item) {
// In case we cannot determine the width, just set it to the default css value
$width = 'auto';
// find an img or object tag within the [caption] to determine the width
if (preg_match_all('/<(img|object)[^>]+>/i', $item, $internal_result)) {
foreach ($internal_result['0'] as $tag) {
// If the width is defined, dump that into the $widths array.
if (preg_match_all('/width="([0-9]*)"/i', $tag, $width_result)) {
$width = $width_result[1][0];
}
else {
preg_match('/src="([^"]*)"/i', $tag, $src_result);
// if there is a src tag
if (!empty($src_result)) {
$src = $src_result['1'];
$parts = parse_url($src);
if (empty($parts['scheme'])) {
// getcwd() is based off index.php's location, but we'll filter
// out the caption_filter path just in case
$drupal_root = str_replace(drupal_get_path('module', 'caption_filter'), '', getcwd());
// Remove any query string attached to the images, as query strings
// break getimagesize()
if (!empty($parts['query'])) {
$local_path = $drupal_root . str_replace('?' . $parts['query'], '', $src);
}
else {
$local_path = $drupal_root . $src;
}
list($width) = getimagesize($local_path);
}
else {
list($width) = getimagesize($src_result[1]);
}
}
}
}
}
// Free up memory.
unset($src_result, $width_result, $internal_result, $tag, $item);
// We need to append the 'px' to any numeric widths.
if (is_numeric($width)) {
$width = $width . 'px';
}
return $width;
}
/**
* Retrieve all attributes from a caption "shortcode" tag.
*
* This code is based upon the WordPress function shortcode_parse_atts().
*
* @see http://core.svn.wordpress.org/branches/3.2/wp-includes/shortcodes.php
*
* @param $text
* The shortcode tag attributes to be parsed. This should not include the
* brackets, the tag itself, or any of the contents within the tag. It should
* be a string of attributes, such as:
*
* @code
* attr1="value 1" attr2=value2 value3
* @endcode
*
* Note that these tags may or may not use quotes, either single or double.
* @return
* An array of attributes and their value.
*/
function _caption_filter_tag_attributes($text) {
$atts = array();
$pattern = '/(\\w+)\\s*=\\s*"([^"]*)"(?:\\s|$)|(\\w+)\\s*=\\s*\'([^\']*)\'(?:\\s|$)|(\\w+)\\s*=\\s*([^\\s\'"]+)(?:\\s|$)|"([^"]*)"(?:\\s|$)|(\\S+)(?:\\s|$)/';
$text = preg_replace("/[\\x{00a0}\\x{200b}]+/u", " ", $text);
if (preg_match_all($pattern, $text, $match, PREG_SET_ORDER)) {
foreach ($match as $m) {
if (!empty($m[1])) {
$atts[strtolower($m[1])] = stripcslashes($m[2]);
}
elseif (!empty($m[3])) {
$atts[strtolower($m[3])] = stripcslashes($m[4]);
}
elseif (!empty($m[5])) {
$atts[strtolower($m[5])] = stripcslashes($m[6]);
}
elseif (isset($m[7]) and strlen($m[7])) {
$atts[strtolower($m[7])] = TRUE;
}
elseif (isset($m[8])) {
$atts[strtolower($m[8])] = TRUE;
}
}
}
else {
$atts = ltrim($text);
}
return $atts;
}
/**
* Implements hook_wysiwyg_plugin().
*
* This hook returns a list of plugins written directly against certain WYSIWYG
* editors.
*/
function caption_filter_wysiwyg_plugin($editor, $version) {
$plugins = array();
if ($editor == 'tinymce') {
$plugins['captionfilter'] = array(
'url' => 'http://drupal.org/project/caption_filter',
'path' => drupal_get_path('module', 'caption_filter') . '/js',
'filename' => 'caption-filter-tinymce.js',
// Caption Filter doesn't actually provide a button, but this code is
// needed to make it so that WYSIWYG module will load our plugin.
'buttons' => array(
'captionfilter' => t('Caption Filter'),
),
'options' => array(
'captionfilter_css' => base_path() . drupal_get_path('module', 'caption_filter') . '/caption-filter.css',
),
'load' => TRUE,
);
}
return $plugins;
}
/**
* Implements hook_element_info().
*/
function caption_filter_elements() {
// We only enhance widgets if the Insert module is available.
if (!function_exists('insert_widgets')) {
return;
}
$extra = array(
'#after_build' => array(
'caption_filter_element_process',
),
);
$elements = array();
foreach (insert_widgets() as $widget_type => $widget) {
if (isset($widget['fields']['title'])) {
$element_type = isset($widget['element_type']) ? $widget['element_type'] : $widget_type;
$elements[$element_type] = $extra;
}
}
return $elements;
}
/**
* Form API #process function for elements.
*/
function caption_filter_element_process($element) {
static $js_added;
$field = content_fields($element['#field_name'], $element['#type_name']);
$widget_settings = $field['widget'];
$widget_type = $field['widget']['type'];
if (isset($element['data']['title'])) {
$element['data']['title']['#title'] = t('Caption');
$element['data']['title']['#description'] = NULL;
// Add settings for this widget only once.
if (!isset($js_added[$widget_type])) {
$js_added[$widget_type] = TRUE;
$caption_settings = array(
'captionFromTitle' => $widget_settings['caption_from_title'],
);
drupal_add_js(array(
'captionFilter' => array(
'widgets' => array(
$widget_type => $caption_settings,
),
),
), 'setting');
}
}
return $element;
}
/**
* Implementation of hook_widget_settings_alter().
*/
function caption_filter_widget_settings_alter(&$settings, $op, $widget) {
// Only support modules that implement hook_insert_widgets().
$widget_type = isset($widget['widget_type']) ? $widget['widget_type'] : $widget['type'];
if (!function_exists('insert_widgets') || !in_array($widget_type, array_keys(insert_widgets()))) {
return;
}
// Add our new options to the list of settings to be saved.
if ($op == 'save') {
$settings = array_merge($settings, caption_filter_widget_settings());
}
// Add the additional settings to the form.
if ($op == 'form' && isset($settings['title_settings']['custom_title'])) {
$settings['insert'] = array_merge($settings['insert'], caption_filter_widget_form($widget));
}
}
/**
* A list of settings needed by Caption Filter module on widgets.
*/
function caption_filter_widget_settings() {
return array(
'caption_from_title',
);
}
/**
* Configuration form for editing insert settings for a field instance.
*/
function caption_filter_widget_form($widget) {
$settings = $widget['settings'];
$form['caption_from_title'] = array(
'#type' => 'checkbox',
'#title' => t('Use the <em>Title</em> field as a caption'),
'#default_value' => isset($settings['caption_from_title']) ? $settings['caption_from_title'] : 1,
'#element_validate' => array(
'caption_filter_field_widget_caption_validate',
),
'#description' => t('This feature requires that the <em>Title</em> field be enabled above, and that the "Caption filter" be enabled in the <a href="!formats">input formats configuration</a>.', array(
'!formats' => url('admin/settings/filters'),
)),
'#weight' => -9,
);
return $form;
}
/**
* An #element_validate function for the "caption_from_title" field.
*/
function caption_filter_field_widget_caption_validate($element, &$form_state) {
if ($element['#value'] && empty($form_state['values']['custom_title'])) {
form_error($element, t('The <em>Title</em> field must be enabled to use it as a caption.'));
}
}
Functions
Name![]() |
Description |
---|---|
caption_filter_elements | Implements hook_element_info(). |
caption_filter_element_process | Form API #process function for elements. |
caption_filter_field_widget_caption_validate | An #element_validate function for the "caption_from_title" field. |
caption_filter_filter | Implementation of hook_filter(). |
caption_filter_filter_tips | Implementation of hook_filter_tips(). |
caption_filter_init | Implementation of hook_init(). |
caption_filter_process_filter | Filter process callback. Replace the [caption] tags with HTML. |
caption_filter_widget_form | Configuration form for editing insert settings for a field instance. |
caption_filter_widget_settings | A list of settings needed by Caption Filter module on widgets. |
caption_filter_widget_settings_alter | Implementation of hook_widget_settings_alter(). |
caption_filter_wysiwyg_plugin | Implements hook_wysiwyg_plugin(). |
_caption_filter_get_width | Determine the width of the img/object that is being captioned. |
_caption_filter_replace | Callback for preg_replace_callback() in caption_filter_process_filter(). |
_caption_filter_tag_attributes | Retrieve all attributes from a caption "shortcode" tag. |