diff --git a/core/modules/filter/filter.admin.js b/core/modules/filter/filter.admin.js
index f55159a..123576a 100644
--- a/core/modules/filter/filter.admin.js
+++ b/core/modules/filter/filter.admin.js
@@ -33,7 +33,7 @@ Drupal.behaviors.filterStatus = {
}
}
// Restripe table after toggling visibility of table row.
- Drupal.tableDrag['filter-order'].restripeTable();
+ Drupal.tableDrag['edit-filters-order'].restripeTable();
});
// Attach summary for configurable filters (only for screen-readers).
diff --git a/core/modules/filter/filter.api.php b/core/modules/filter/filter.api.php
index 49311c8..94632a3 100644
--- a/core/modules/filter/filter.api.php
+++ b/core/modules/filter/filter.api.php
@@ -130,6 +130,28 @@ function hook_filter_info_alter(&$info) {
}
/**
+ * Alters images with an invalid source.
+ *
+ * When the 'Restrict images to this site' filter is enabled, any images that
+ * are not hosted on the site will be passed through this hook, most commonly to
+ * replace the invalid image with an error indicator.
+ *
+ * @param DOMElement $image
+ * An IMG node to format, parsed from the filtered text.
+ */
+function hook_filter_secure_image_alter(&$image) {
+ // Turn an invalid image into an error indicator.
+ $image->setAttribute('src', base_path() . 'core/misc/message-16-error.png');
+ $image->setAttribute('alt', t('Image removed.'));
+ $image->setAttribute('title', t('This image has been removed. For security reasons, only images from the local domain are allowed.'));
+
+ // Add a CSS class to aid in styling.
+ $class = ($image->getAttribute('class') ? trim($image->getAttribute('class')) . ' ' : '');
+ $class .= 'filter-image-invalid';
+ $image->setAttribute('class', $class);
+}
+
+/**
* @} End of "addtogroup hooks".
*/
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 57ff8c2..2648d8b 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -70,18 +70,15 @@ function filter_theme() {
'filter_tips' => array(
'variables' => array('tips' => NULL, 'long' => FALSE),
'file' => 'filter.pages.inc',
+ 'template' => 'filter-tips',
),
'text_format_wrapper' => array(
- 'render element' => 'element',
- ),
- 'filter_tips_more_info' => array(
- 'variables' => array(),
+ 'variables' => array('children' => NULL, 'description' => NULL),
+ 'template' => 'text-format-wrapper',
),
'filter_guidelines' => array(
'variables' => array('format' => NULL),
- ),
- 'filter_html_image_secure_image' => array(
- 'variables' => array('image' => NULL),
+ 'template' => 'filter-guidelines',
),
);
}
@@ -865,11 +862,23 @@ function filter_process_format($element) {
'#parents' => array_merge($element['#parents'], array('format')),
);
+ $filter_tips_link = array(
+ '#theme' => 'link',
+ '#text' => t('More information about text formats'),
+ '#path' => 'filter/tips',
+ '#options' => array(
+ 'attributes' => array('target' => '_blank'),
+ 'html' => FALSE,
+ ),
+ '#prefix' => '
',
+ '#suffix' => '
',
+ );
+
$element['format']['help'] = array(
'#type' => 'container',
- '#theme' => 'filter_tips_more_info',
'#attributes' => array('class' => array('filter-help')),
'#weight' => 0,
+ $filter_tips_link,
);
$all_formats = filter_formats();
@@ -935,27 +944,6 @@ function filter_form_access_denied($element) {
}
/**
- * Returns HTML for a text format-enabled form element.
- *
- * @param array $variables
- * An associative array containing:
- * - element: A render element containing #children and #description.
- *
- * @ingroup themeable
- */
-function theme_text_format_wrapper($variables) {
- $element = $variables['element'];
- $output = '';
- $output .= $element['#children'];
- if (!empty($element['#description'])) {
- $output .= '
' . $element['#description'] . '
';
- }
- $output .= "
\n";
-
- return $output;
-}
-
-/**
* Checks if a user has access to a particular text format.
*
* @param $format
@@ -1126,32 +1114,84 @@ function filter_dom_serialize_escape_cdata_element($dom_document, $dom_element,
}
/**
- * Returns HTML for a link to the more extensive filter tips.
+ * Prepares variables for text format guideline templates.
*
- * @ingroup themeable
+ * Default template: filter-guidelines.html.twig.
+ *
+ * @param array $variables
+ * An associative array containing:
+ * - format: An object representing a text format.
*/
-function theme_filter_tips_more_info() {
- return '' . l(t('More information about text formats'), 'filter/tips', array('attributes' => array('target' => '_blank'))) . '
';
+function template_preprocess_filter_guidelines(&$variables) {
+ $format = $variables['format'];
+ // Remove any classes added by template_preprocess().
+ // @todo Remove line below after http://drupal.org/node/1938430 is resolved.
+ $variables['attributes']['class'] = array();
+ $variables['attributes']['class'][] = 'filter-guidelines-item';
+ $variables['attributes']['class'][] = 'filter-guidelines-' . $format->format;
+ $variables['attributes'] = new Attribute($variables['attributes']);
+
+ $variables['tips'] = array(
+ '#theme' => 'filter_tips',
+ '#tips' => _filter_tips($format->format, FALSE),
+ );
}
/**
- * Returns HTML for guidelines for a text format.
+ * Prepares variables for filter tips templates.
+ *
+ * Default template: filter-tips.html.twig.
*
* @param array $variables
* An associative array containing:
- * - format: An object representing a text format.
- *
- * @ingroup themeable
+ * - tips: An array containing descriptions and a CSS ID in the form of
+ * 'module-name/filter-id' (only used when $long is TRUE) for each
+ * filter in one or more text formats. Example:
+ * @code
+ * array(
+ * 'Full HTML' => array(
+ * 0 => array(
+ * 'tip' => 'Web page addresses and e-mail addresses turn into links automatically.',
+ * 'id' => 'filter/2',
+ * ),
+ * ),
+ * );
+ * @endcode
+ * - long: (optional) Whether the passed-in filter tips contain extended
+ * explanations, i.e. intended to be output on the path 'filter/tips'
+ * (TRUE), or are in a short format, i.e. suitable to be displayed below a
+ * form element. Defaults to FALSE.
*/
-function theme_filter_guidelines($variables) {
- $format = $variables['format'];
- $attributes['class'][] = 'filter-guidelines-item';
- $attributes['class'][] = 'filter-guidelines-' . $format->format;
- $output = '';
- $output .= '
' . check_plain($format->name) . '
';
- $output .= theme('filter_tips', array('tips' => _filter_tips($format->format, FALSE)));
- $output .= '';
- return $output;
+function template_preprocess_filter_tips(&$variables) {
+ $tips = $variables['tips'];
+ $long = $variables['long'];
+ $output = '';
+
+ $multiple = count($tips) > 1;
+
+ foreach ($variables['tips'] as $name => $tiplist) {
+ foreach ($tiplist as $tip_key => $tip) {
+ $tiplist[$tip_key]['attributes'] = new Attribute(array());
+ if ($long) {
+ $tiplist[$tip_key]['attributes']['class'] = array('filter-' . str_replace("/", "-", $tip['id']));
+ }
+ }
+
+ $attributes = array(
+ 'class' => array(
+ 'filter-type',
+ 'filter-' . drupal_html_class($name),
+ ),
+ );
+
+ $variables['tips'][$name] = array(
+ 'attributes' => new Attribute($attributes),
+ 'name' => check_plain($name),
+ 'list' => $tiplist,
+ );
+ }
+
+ $variables['multiple'] = $multiple;
}
/**
@@ -1756,28 +1796,25 @@ function _filter_html_image_secure_process($text) {
continue;
}
}
- // Replace an invalid image with an error indicator.
- theme('filter_html_image_secure_image', array('image' => $image));
+ // Allow modules and themes to replace an invalid image with an error
+ // indicator. See filter_filter_secure_image_alter().
+ drupal_alter('filter_secure_image', $image);
}
$text = filter_dom_serialize($html_dom);
return $text;
}
/**
+ * Implements hook_filter_secure_image_alter().
+ *
* Formats an image DOM element that has an invalid source.
*
* @param DOMElement $image
* An IMG node to format, parsed from the filtered text.
*
- * @return void
- * Unlike other theme functions, the passed in $image is altered by reference.
- *
* @see _filter_html_image_secure_process()
- * @ingroup themeable
*/
-function theme_filter_html_image_secure_image(&$variables) {
- $image = $variables['image'];
-
+function filter_filter_secure_image_alter(&$image) {
// Turn an invalid image into an error indicator.
$image->setAttribute('src', base_path() . 'core/misc/message-16-error.png');
$image->setAttribute('alt', t('Image removed.'));
diff --git a/core/modules/filter/filter.pages.inc b/core/modules/filter/filter.pages.inc
index 5b20d4f..f0ac5d6 100644
--- a/core/modules/filter/filter.pages.inc
+++ b/core/modules/filter/filter.pages.inc
@@ -19,76 +19,18 @@
*/
function filter_tips_long($format = NULL) {
if (!empty($format)) {
- $output = theme('filter_tips', array('tips' => _filter_tips($format->format, TRUE), 'long' => TRUE));
+ $filter_tips = array(
+ '#theme' => 'filter_tips',
+ '#tips' => _filter_tips($format->format, TRUE),
+ '#long' => TRUE,
+ );
}
else {
- $output = theme('filter_tips', array('tips' => _filter_tips(-1, TRUE), 'long' => TRUE));
+ $filter_tips = array(
+ '#theme' => 'filter_tips',
+ '#tips' => _filter_tips(-1, TRUE),
+ '#long' => TRUE,
+ );
}
- return $output;
-}
-
-/**
- * Returns HTML for a set of filter tips.
- *
- * @param array $variables
- * An associative array containing:
- * - tips: An array containing descriptions and a CSS ID in the form of
- * 'module-name/filter-id' (only used when $long is TRUE) for each
- * filter in one or more text formats. Example:
- * @code
- * array(
- * 'Full HTML' => array(
- * 0 => array(
- * 'tip' => 'Web page addresses and e-mail addresses turn into links automatically.',
- * 'id' => 'filter/2',
- * ),
- * ),
- * );
- * @endcode
- * - long: (optional) Whether the passed-in filter tips contain extended
- * explanations, i.e. intended to be output on the path 'filter/tips'
- * (TRUE), or are in a short format, i.e. suitable to be displayed below a
- * form element. Defaults to FALSE.
- *
- * @see _filter_tips()
- * @ingroup themeable
- */
-function theme_filter_tips($variables) {
- $tips = $variables['tips'];
- $long = $variables['long'];
- $output = '';
-
- $multiple = count($tips) > 1;
- if ($multiple) {
- $output = '' . t('Text Formats') . '
';
- }
-
- if (count($tips)) {
- if ($multiple) {
- $output .= '';
- }
- foreach ($tips as $name => $tiplist) {
- if ($multiple) {
- $output .= '
';
- $output .= '
' . $name . '
';
- }
-
- if (count($tiplist) > 0) {
- $output .= '
';
- foreach ($tiplist as $tip) {
- $output .= '- ' : '>') . $tip['tip'] . '
';
- }
- $output .= '
';
- }
-
- if ($multiple) {
- $output .= '
';
- }
- }
- if ($multiple) {
- $output .= '
';
- }
- }
-
- return $output;
+ return $filter_tips;
}
diff --git a/core/modules/filter/templates/filter-guidelines.html.twig b/core/modules/filter/templates/filter-guidelines.html.twig
new file mode 100644
index 0000000..e4311f4
--- /dev/null
+++ b/core/modules/filter/templates/filter-guidelines.html.twig
@@ -0,0 +1,28 @@
+{#
+/**
+ * @file
+ * Default theme implementation for guidelines for a text format.
+ *
+ * Available variables:
+ * - format: Contains information about the current text format, including the
+ * following:
+ * - format.name: The name of the text format.
+ * - format.format: The machine name of the text format, e.g. 'basic_html'.
+ * - attributes: HTML attributes for the containing element.
+ * - tips: Descriptions and a CSS ID in the form of 'module-name/filter-id'
+ * (only used when 'long' is TRUE) for each filter in one or more text
+ * formats.
+ *
+ * @todo Remove striptags when auto_escape is resolved
+ * http://drupal.org/node/1712444.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_filter_tips()
+ *
+ * @ingroup themeable
+ */
+#}
+
+
{{ format.name|striptags }}
+ {{ tips }}
+
diff --git a/core/modules/filter/templates/filter-tips.html.twig b/core/modules/filter/templates/filter-tips.html.twig
new file mode 100644
index 0000000..0486ce3
--- /dev/null
+++ b/core/modules/filter/templates/filter-tips.html.twig
@@ -0,0 +1,55 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a set of filter tips.
+ *
+ * Available variables:
+ * - tips: Descriptions and a CSS id in the form of 'module-name/filter-id'
+ * (only used when 'long' is TRUE) for each filter in one or more text
+ * formats.
+ * - long: (optional) Whether the passed-in filter tips contain extended
+ * explanations, i.e. intended to be output on the path 'filter/tips'
+ * (TRUE), or are in a short format, i.e. suitable to be displayed below a
+ * form element. Defaults to FALSE.
+ *
+ * @todo Reimplement once http://drupal.org/node/1778624 gets resolved.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_filter_tips()
+ *
+ * @ingroup themeable
+ */
+#}
+{% if multiple %}
+ {{ 'Text Formats'|t }}
+{% endif %}
+
+{% if tips|length %}
+ {% if multiple %}
+
+ {% endif %}
+
+ {% for tip in tips %}
+ {% if multiple %}
+
+
{{ tip.name }}
+ {% endif %}
+
+ {% if tip.list|length %}
+
+ {% for item in tip.list %}
+ {# Only set the class if the type is long. #}
+ - {{ item.tip }}
+ {% endfor %}
+
+ {% endif %}
+
+ {% if multiple %}
+
+ {% endif %}
+ {% endfor %}
+
+ {% if multiple %}
+
+ {% endif %}
+{% endif %}
diff --git a/core/modules/filter/templates/text-format-wrapper.html.twig b/core/modules/filter/templates/text-format-wrapper.html.twig
new file mode 100644
index 0000000..331b81e
--- /dev/null
+++ b/core/modules/filter/templates/text-format-wrapper.html.twig
@@ -0,0 +1,21 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a text format-enabled form element.
+ *
+ * Available variables:
+ * - children: Text format element children.
+ * - description: Text format element description.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_text_format_wrapper()
+ *
+ * @ingroup themeable
+ */
+#}
+
+ {{ children }}
+ {% if description %}
+
{{ description }}
+ {% endif %}
+