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 8d6aa01..7f2c132 100644 --- a/core/modules/filter/filter.api.php +++ b/core/modules/filter/filter.api.php @@ -24,6 +24,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); +} + +/** * Perform actions when a text format has been disabled. * * @param $format diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 06d3fff..6bf6830 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -78,18 +78,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', ), ); } @@ -759,9 +756,11 @@ function filter_process_format($element) { $element['format']['help'] = array( '#type' => 'container', - '#theme' => 'filter_tips_more_info', '#attributes' => array('class' => array('filter-help')), '#weight' => 0, + '#markup' => l(t('More information about text formats'), 'filter/tips', array('attributes' => array('target' => '_blank'))), + '#prefix' => '

', + '#suffix' => '

', ); $all_formats = filter_formats(); @@ -827,27 +826,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 @@ -1016,32 +994,88 @@ 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 default 'filter-guidelines' class from attributes, but leave other + // classes. + // @todo: Remove this hack once http://drupal.org/node/1938430 lands. + $key = array_search('filter-guidelines', $variables['attributes']['class']->value()); + if ($key !== FALSE) { + unset($variables['attributes']['class'][$key]); + } + $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; } /** @@ -1408,28 +1442,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::moduleHandler()->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..b11562e --- /dev/null +++ b/core/modules/filter/templates/filter-tips.html.twig @@ -0,0 +1,54 @@ +{# +/** + * @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: A flag indicating 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 %} + {{ 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 %} +