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 4962044..a349add 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -80,16 +80,15 @@ function filter_theme() { return array( 'filter_tips' => array( 'variables' => array('tips' => NULL, 'long' => FALSE), - 'file' => 'filter.pages.inc', + 'template' => 'filter-tips', ), 'text_format_wrapper' => array( - 'render element' => 'element', + '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', ), 'filter_caption' => array( 'variables' => array( @@ -831,27 +830,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; -} - -/** * Retrieves the filter tips. * * @param string $format_id @@ -991,27 +969,77 @@ function filter_dom_serialize_escape_cdata_element($dom_document, $dom_element, } /** - * Returns HTML for guidelines for a text format. + * Prepares variables for text format guideline templates. + * + * Default template: filter-guidelines.html.twig. * * @param array $variables * An associative array containing: * - format: An object representing a text format. - * - * @ingroup themeable */ -function theme_filter_guidelines($variables) { +function template_preprocess_filter_guidelines(&$variables) { $format = $variables['format']; - $attributes['class'][] = 'filter-guidelines-item'; - $attributes['class'][] = 'filter-guidelines-' . $format->format; - $output = ''; - $output .= '

' . check_plain($format->name) . '

'; - $filter_tips = array( + $variables['attributes']['class'][] = 'filter-guidelines-item'; + $variables['attributes']['class'][] = 'filter-guidelines-' . $format->format; + + $variables['tips'] = array( '#theme' => 'filter_tips', '#tips' => _filter_tips($format->format, FALSE), ); - $output .= drupal_render($filter_tips); - $output .= ''; - return $output; +} + +/** + * Prepares variables for filter tips templates. + * + * Default template: filter-tips.html.twig. + * + * @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. + */ +function template_preprocess_filter_tips(&$variables) { + $tips = $variables['tips']; + $long = $variables['long']; + + 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'] = count($tips) > 1; } /** @@ -1391,32 +1419,25 @@ function _filter_html_image_secure_process($text) { continue; } } - // Replace an invalid image with an error indicator. - $filter_html_image_secure_image = array( - '#theme' => 'filter_html_image_secure_image', - '#image' => $image, - ); - drupal_render($filter_html_image_secure_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 deleted file mode 100644 index 8f2e298..0000000 --- a/core/modules/filter/filter.pages.inc +++ /dev/null @@ -1,72 +0,0 @@ - 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; -} diff --git a/core/modules/filter/lib/Drupal/filter/Controller/FilterController.php b/core/modules/filter/lib/Drupal/filter/Controller/FilterController.php index ca4e733..ae8bc01 100644 --- a/core/modules/filter/lib/Drupal/filter/Controller/FilterController.php +++ b/core/modules/filter/lib/Drupal/filter/Controller/FilterController.php @@ -23,7 +23,7 @@ class FilterController { * @return array * A renderable array. * - * @see theme_filter_tips() + * @see template_preprocess_filter_tips() */ function filterTips(FilterFormatInterface $filter_format = NULL) { $tips = $filter_format ? $filter_format->format : -1; diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php index 40156e4..1d0df9e 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php @@ -262,7 +262,7 @@ public function getHTMLRestrictions(); * @param bool $long * Whether this callback should return a short tip to display in a form * (FALSE), or whether a more elaborate filter tips should be returned for - * theme_filter_tips() (TRUE). + * template_preprocess_filter_tips() (TRUE). * * @return string|null * Translated text to display as a tip, or NULL if this filter has no tip. 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..4dd849d --- /dev/null +++ b/core/modules/filter/templates/filter-guidelines.html.twig @@ -0,0 +1,24 @@ +{# +/** + * @file + * Default theme implementation for guidelines for a text format. + * + * Available variables: + * - format: Contains information about the current text format, including the + * following: + * - name: The name of the text 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. + * + * @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..d8f70cb --- /dev/null +++ b/core/modules/filter/templates/filter-tips.html.twig @@ -0,0 +1,52 @@ +{# +/** + * @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. + * - multiple: A flag indicating there is more than one filter tip. + * + * @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..f453971 --- /dev/null +++ b/core/modules/filter/templates/text-format-wrapper.html.twig @@ -0,0 +1,18 @@ +{# +/** + * @file + * Default theme implementation for a text format-enabled form element. + * + * Available variables: + * - children: Text format element children. + * - description: Text format element description. + * + * @ingroup themeable + */ +#} +
+ {{ children }} + {% if description %} +
{{ description }}
+ {% endif %} +