Commit 7922db66 authored by alexpott's avatar alexpott

Issue #1423244 by tstoeckler, floretan, Wim Leers, lokapujya, xjm, webflo:...

Issue #1423244 by tstoeckler, floretan, Wim Leers, lokapujya, xjm, webflo: #allowed_formats property for #type 'text_format' to filter available formats.
parent e0b25fcb
......@@ -496,8 +496,11 @@ function check_markup($text, $format_id = NULL, $langcode = '', $filter_types_to
* The form element to process. Properties used:
* - #base_type: The form element #type to use for the 'value' element.
* 'textarea' by default.
* - #format: (optional) The text format ID to preselect. If NULL or not set,
* the default format for the current user will be used.
* - #format: (optional) The text format ID to preselect. If omitted, the
* default format for the current user will be used.
* - #allowed_formats: (optional) An array of text format IDs that are
* available for this element. If omitted, all text formats that the current
* user has access to will be allowed.
*
* @return
* The expanded element.
......@@ -536,6 +539,8 @@ function filter_process_format($element) {
$element['value']['#type'] = $element['#base_type'];
$element['value'] += element_info($element['#base_type']);
// Make sure the #default_value key is set, so we can use it below.
$element['value'] += array('#default_value' => '');
// Turn original element into a text format wrapper.
$element['#attached']['library'][] = 'filter/drupal.filter';
......@@ -549,15 +554,30 @@ function filter_process_format($element) {
// Get a list of formats that the current user has access to.
$formats = filter_formats($user);
// Use the default format for this user if none was selected.
if (!isset($element['#format'])) {
$element['#format'] = filter_default_format($user);
// Allow the list of formats to be restricted.
if (isset($element['#allowed_formats'])) {
// We do not add the fallback format here to allow the use-case of forcing
// certain text formats to be used for certain text areas. In case the
// fallback format is supposed to be allowed as well, it must be added to
// $element['#allowed_formats'] explicitly.
$formats = array_intersect_key($formats, array_flip($element['#allowed_formats']));
}
// If multiple text formats are available, remove the fallback. The
// "always_show_fallback_choice" is a hidden variable that has no UI. It
// defaults to false.
if (!\Drupal::config('filter.settings')->get('always_show_fallback_choice')) {
if (!isset($element['#format']) && !empty($formats)) {
// If no text format was selected, use the allowed format with the highest
// weight. This is equivalent to calling filter_default_format().
$element['#format'] = reset($formats)->format;
}
// If #allowed_formats is set, the list of formats must not be modified in any
// way. Otherwise, however, if all of the following conditions are true,
// remove the fallback format from the list of formats:
// 1. The 'always_show_fallback_choice' filter setting has not been activated.
// 2. Multiple text formats are available.
// 3. The fallback format is not the default format.
// The 'always_show_fallback_choice' filter setting is a hidden setting that
// has no UI. It defaults to FALSE.
if (!isset($element['#allowed_formats']) && !\Drupal::config('filter.settings')->get('always_show_fallback_choice')) {
$fallback_format = filter_fallback_format();
if ($element['#format'] !== $fallback_format && count($formats) > 1) {
unset($formats[$fallback_format]);
......@@ -599,12 +619,13 @@ function filter_process_format($element) {
$all_formats = filter_formats();
$format_exists = isset($all_formats[$element['#format']]);
$format_allowed = !isset($element['#allowed_formats']) || in_array($element['#format'], $element['#allowed_formats']);
$user_has_access = isset($formats[$element['#format']]);
$user_is_admin = user_access('administer filters');
// If the stored format does not exist, administrators have to assign a new
// format.
if (!$format_exists && $user_is_admin) {
// If the stored format does not exist or if it is not among the allowed
// formats for this textarea, administrators have to assign a new format.
if ((!$format_exists || !$format_allowed) && $user_is_admin) {
$element['format']['format']['#required'] = TRUE;
$element['format']['format']['#default_value'] = NULL;
// Force access to the format selector (it may have been denied above if
......
......@@ -24,7 +24,7 @@ class FilterAPITest extends EntityUnitTestBase {
public static function getInfo() {
return array(
'name' => 'API',
'name' => 'Filter API',
'description' => 'Test the behavior of the API of the Filter module.',
'group' => 'Filter',
);
......@@ -34,36 +34,6 @@ function setUp() {
parent::setUp();
$this->installConfig(array('system', 'filter'));
// Create Filtered HTML format.
$filtered_html_format = entity_create('filter_format', array(
'format' => 'filtered_html',
'name' => 'Filtered HTML',
'filters' => array(
// Note that the filter_html filter is of the type FilterInterface::TYPE_MARKUP_LANGUAGE.
'filter_url' => array(
'weight' => -1,
'status' => 1,
),
// Note that the filter_html filter is of the type FilterInterface::TYPE_HTML_RESTRICTOR.
'filter_html' => array(
'status' => 1,
'settings' => array(
'allowed_html' => '<p> <br> <strong> <a>',
),
),
)
));
$filtered_html_format->save();
// Create Full HTML format.
$full_html_format = entity_create('filter_format', array(
'format' => 'full_html',
'name' => 'Full HTML',
'weight' => 1,
'filters' => array(),
));
$full_html_format->save();
}
/**
......@@ -105,13 +75,17 @@ function testCheckMarkupFilterSubset() {
$expected_filtered_text = "Text with evil content and a URL: <a href=\"http://drupal.org\">http://drupal.org</a>!";
$expected_filter_text_without_html_generators = "Text with evil content and a URL: http://drupal.org!";
$actual_filtered_text = check_markup($text, 'filtered_html', '', array());
$this->verbose("Actual:<pre>$actual_filtered_text</pre>Expected:<pre>$expected_filtered_text</pre>");
$this->assertIdentical(
check_markup($text, 'filtered_html', '', array()),
$actual_filtered_text,
$expected_filtered_text,
'Expected filter result.'
);
$actual_filtered_text_without_html_generators = check_markup($text, 'filtered_html', '', array(FilterInterface::TYPE_MARKUP_LANGUAGE));
$this->verbose("Actual:<pre>$actual_filtered_text_without_html_generators</pre>Expected:<pre>$expected_filter_text_without_html_generators</pre>");
$this->assertIdentical(
check_markup($text, 'filtered_html', '', array(FilterInterface::TYPE_MARKUP_LANGUAGE)),
$actual_filtered_text_without_html_generators,
$expected_filter_text_without_html_generators,
'Expected filter result when skipping FilterInterface::TYPE_MARKUP_LANGUAGE filters.'
);
......@@ -119,8 +93,10 @@ function testCheckMarkupFilterSubset() {
// this check focuses on the ability to filter multiple filter types at once.
// Drupal core only ships with these two types of filters, so this is the
// most extensive test possible.
$actual_filtered_text_without_html_generators = check_markup($text, 'filtered_html', '', array(FilterInterface::TYPE_HTML_RESTRICTOR, FilterInterface::TYPE_MARKUP_LANGUAGE));
$this->verbose("Actual:<pre>$actual_filtered_text_without_html_generators</pre>Expected:<pre>$expected_filter_text_without_html_generators</pre>");
$this->assertIdentical(
check_markup($text, 'filtered_html', '', array(FilterInterface::TYPE_HTML_RESTRICTOR, FilterInterface::TYPE_MARKUP_LANGUAGE)),
$actual_filtered_text_without_html_generators,
$expected_filter_text_without_html_generators,
'Expected filter result when skipping FilterInterface::TYPE_MARKUP_LANGUAGE filters, even when trying to disable filters of the FilterInterface::TYPE_HTML_RESTRICTOR type.'
);
......
This diff is collapsed.
......@@ -31,7 +31,7 @@ class FilterSecurityTest extends WebTestBase {
public static function getInfo() {
return array(
'name' => 'Security',
'name' => 'Filter security',
'description' => 'Test the behavior of check_markup() when a filter or text format vanishes, or when check_markup() is called in such a way that it is instructed to skip all filters of the "FilterInterface::TYPE_HTML_RESTRICTOR" type.',
'group' => 'Filter',
);
......@@ -43,19 +43,8 @@ function setUp() {
// Create Basic page node type.
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
// Create Filtered HTML format.
$filtered_html_format = entity_create('filter_format', array(
'format' => 'filtered_html',
'name' => 'Filtered HTML',
'filters' => array(
// Note that the filter_html filter is of the type FilterInterface::TYPE_HTML_RESTRICTOR.
'filter_html' => array(
'status' => 1,
),
)
));
$filtered_html_format->save();
/** @var \Drupal\filter\Entity\FilterFormat $filtered_html_format */
$filtered_html_format = entity_load('filter_format', 'filtered_html');
$filtered_html_permission = $filtered_html_format->getPermissionName();
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array($filtered_html_permission));
......@@ -100,8 +89,8 @@ function testDisableFilterModule() {
* Tests that security filters are enforced even when marked to be skipped.
*/
function testSkipSecurityFilters() {
$text = "Text with some disallowed tags: <script />, <em><object>unicorn</object></em>, <i><table></i>.";
$expected_filtered_text = "Text with some disallowed tags: , <em>unicorn</em>, .";
$text = "Text with some disallowed tags: <script />, <p><object>unicorn</object></p>, <i><table></i>.";
$expected_filtered_text = "Text with some disallowed tags: , <p>unicorn</p>, .";
$this->assertEqual(check_markup($text, 'filtered_html', '', array()), $expected_filtered_text, 'Expected filter result.');
$this->assertEqual(check_markup($text, 'filtered_html', '', array(FilterInterface::TYPE_HTML_RESTRICTOR)), $expected_filtered_text, 'Expected filter result, even when trying to disable filters of the FilterInterface::TYPE_HTML_RESTRICTOR type.');
}
......
format: filtered_html
name: 'Filtered HTML'
weight: 1
filters:
filter_url:
id: filter_url
provider: filter
weight: -1
status: true
filter_html:
id: filter_html
provider: filter
status: true
settings:
allowed_html: '<p> <br> <strong> <a>'
filter_text.text_format:
path: '/filter-test/text-format'
defaults:
_title: 'Text format test forms'
_form: 'Drupal\filter_test\Form\FilterTestFormatForm'
requirements:
_access: 'TRUE'
<?php
/**
* @file
* Contains \Drupal\filter_test\Form\FilterTestFormatForm.
*/
namespace Drupal\filter_test\Form;
use Drupal\Core\Form\FormBase;
/**
* Shows a test form for testing the 'text_format' form element.
*/
class FilterTestFormatForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'filter_test_format_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state) {
// This ensures that the parent array key makes it into the HTML ID of the
// form elements.
$form['#tree'] = TRUE;
$form['all_formats'] = array(
'#type' => 'details',
'#title' => 'All text formats',
);
$form['all_formats']['no_default'] = array(
'#type' => 'text_format',
'#title' => 'No default value',
);
$form['all_formats']['default'] = array(
'#type' => 'text_format',
'#title' => 'Default value',
'#format' => 'filter_test',
);
$form['all_formats']['default_missing'] = array(
'#type' => 'text_format',
'#title' => 'Missing default value',
'#format' => 'missing_format',
);
$form['restricted_formats'] = array(
'#type' => 'details',
'#title' => 'Restricted text format list',
);
$form['restricted_formats']['no_default'] = array(
'#type' => 'text_format',
'#title' => 'No default value',
'#allowed_formats' => array('full_html', 'filter_test'),
);
$form['restricted_formats']['default'] = array(
'#type' => 'text_format',
'#title' => 'Default value',
'#format' => 'full_html',
'#allowed_formats' => array('full_html', 'filter_test'),
);
$form['restricted_formats']['default_missing'] = array(
'#type' => 'text_format',
'#title' => 'Missing default value',
'#format' => 'missing_format',
'#allowed_formats' => array('full_html', 'filter_test'),
);
$form['restricted_formats']['default_disallowed'] = array(
'#type' => 'text_format',
'#title' => 'Disallowed default value',
'#format' => 'filtered_html',
'#allowed_formats' => array('full_html', 'filter_test'),
);
$form['single_format'] = array(
'#type' => 'details',
'#title' => 'Single text format',
);
$form['single_format']['no_default'] = array(
'#type' => 'text_format',
'#title' => 'No default value',
'#allowed_formats' => array('filter_test'),
);
$form['single_format']['default'] = array(
'#type' => 'text_format',
'#title' => 'Default value',
'#format' => 'filter_test',
'#allowed_formats' => array('filter_test'),
);
$form['single_format']['default_missing'] = array(
'#type' => 'text_format',
'#title' => 'Missing default value',
'#format' => 'missing_format',
'#allowed_formats' => array('filter_test'),
);
$form['single_format']['default_disallowed'] = array(
'#type' => 'text_format',
'#title' => 'Disallowed default value',
'#format' => 'full_html',
'#allowed_formats' => array('filter_test'),
);
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment