Commit 7af2ce77 authored by alexpott's avatar alexpott

Issue #2442255 by swentel, larowlan, rteijeiro, Wim Leers: Changing text...

Issue #2442255 by swentel, larowlan, rteijeiro, Wim Leers: Changing text formats on a field makes it impossible to edit
parent 1dccb946
......@@ -26,7 +26,10 @@
* label = @Translation("CKEditor"),
* supports_content_filtering = TRUE,
* supports_inline_editing = TRUE,
* is_xss_safe = FALSE
* is_xss_safe = FALSE,
* supported_element_types = {
* "textarea"
* }
* )
*/
class CKEditor extends EditorBase implements ContainerFactoryPluginInterface {
......
......@@ -62,4 +62,11 @@ class Editor extends Plugin {
*/
public $is_xss_safe;
/**
* A list of element types this text editor supports.
*
* @var string[]
*/
public $supported_element_types;
}
......@@ -43,6 +43,14 @@ public function getFilterFormat();
*/
public function getEditor();
/**
* Set the text editor plugin ID.
*
* @param string $editor
* The text editor plugin ID to set.
*/
public function setEditor($editor);
/**
* Returns the text editor plugin-specific settings.
*
......
......@@ -53,6 +53,12 @@ function preRenderTextFormat(array $element) {
// Early-return if no text editor is associated with any of the text formats.
$editors = Editor::loadMultiple($format_ids);
foreach ($editors as $key => $editor) {
$definition = $this->pluginManager->getDefinition($editor->getEditor());
if (!in_array($element['#base_type'], $definition['supported_element_types'])) {
unset($editors[$key]);
}
}
if (count($editors) === 0) {
return $element;
}
......
......@@ -141,6 +141,14 @@ public function getEditor() {
return $this->editor;
}
/**
* {@inheritdoc}
*/
public function setEditor($editor) {
$this->editor = $editor;
return $this;
}
/**
* {@inheritdoc}
*/
......
......@@ -7,6 +7,9 @@
namespace Drupal\editor\Tests;
use Drupal\Core\Entity\Entity;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\simpletest\WebTestBase;
/**
......@@ -47,6 +50,10 @@ class EditorLoadingTest extends WebTestBase {
protected function setUp() {
parent::setUp();
// Let there be T-rex.
\Drupal::state()->set('editor_test_give_me_a_trex_thanks', TRUE);
\Drupal::service('plugin.manager.editor')->clearCachedDefinitions();
// Add text formats.
$filtered_html_format = entity_create('filter_format', array(
'format' => 'filtered_html',
......@@ -63,16 +70,42 @@ protected function setUp() {
));
$full_html_format->save();
// Create node type.
// Create article node type.
$this->drupalCreateContentType(array(
'type' => 'article',
'name' => 'Article',
));
// Create page node type, but remove the body.
$this->drupalCreateContentType(array(
'type' => 'page',
'name' => 'Page',
));
$body = FieldConfig::loadByName('node', 'page', 'body');
$body->delete();
// Create a formatted text field, which uses an <input type="text">.
FieldStorageConfig::create(array(
'field_name' => 'field_text',
'entity_type' => 'node',
'type' => 'text',
))->save();
FieldConfig::create(array(
'field_name' => 'field_text',
'entity_type' => 'node',
'label' => 'Textfield',
'bundle' => 'page',
))->save();
entity_get_form_display('node', 'page', 'default')
->setComponent('field_text')
->save();
// Create 3 users, each with access to different text formats.
$this->untrustedUser = $this->drupalCreateUser(array('create article content', 'edit any article content'));
$this->normalUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format filtered_html'));
$this->privilegedUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format filtered_html', 'use text format full_html'));
$this->privilegedUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'create page content', 'edit any page content', 'use text format filtered_html', 'use text format full_html'));
}
/**
......@@ -98,7 +131,7 @@ public function testLoading() {
// - doesn't have access to the full_html text format, so: no text editor.
$this->drupalLogin($this->normalUser);
$this->drupalGet('node/add/article');
list( , $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck();
list( , $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
$this->assertFalse($editor_settings_present, 'No Text Editor module settings.');
$this->assertFalse($editor_js_present, 'No Text Editor JavaScript.');
$this->assertTrue(count($body) === 1, 'A body field exists.');
......@@ -110,7 +143,7 @@ public function testLoading() {
// - does have access to the full_html text format, so: Unicorn text editor.
$this->drupalLogin($this->privilegedUser);
$this->drupalGet('node/add/article');
list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck();
list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
$expected = array('formats' => array('full_html' => array(
'format' => 'full_html',
'editor' => 'unicorn',
......@@ -144,7 +177,7 @@ public function testLoading() {
// - has access to the plain_text text format, so: Unicorn text editor.
$this->drupalLogin($this->untrustedUser);
$this->drupalGet('node/add/article');
list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck();
list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
$expected = array('formats' => array('plain_text' => array(
'format' => 'plain_text',
'editor' => 'unicorn',
......@@ -160,7 +193,7 @@ public function testLoading() {
$hidden_input = $this->xpath('//input[@type="hidden" and @value="plain_text" and contains(@class, "editor") and @data-editor-for="edit-body-0-value"]');
$this->assertTrue(count($hidden_input) === 1, 'A single text format hidden input exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
// Create an "article" node that users the full_html text format, then try
// Create an "article" node that uses the full_html text format, then try
// to let the untrusted user edit it.
$this->drupalCreateNode(array(
'type' => 'article',
......@@ -173,7 +206,7 @@ public function testLoading() {
// that (s)he is not allowed to use. The editor is still loaded. CKEditor,
// for example, supports being loaded in a disabled state.
$this->drupalGet('node/1/edit');
list( , $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck();
list( , $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
$this->assertTrue($editor_settings_present, 'Text Editor module settings.');
$this->assertTrue($editor_js_present, 'Text Editor JavaScript.');
$this->assertTrue(count($body) === 1, 'A body field exists.');
......@@ -183,7 +216,61 @@ public function testLoading() {
$this->assertTrue(count($hidden_input) === 0, 'A single text format hidden input does not exist on the page.');
}
protected function getThingsToCheck() {
/**
* Test supported element types.
*/
public function testSupportedElementTypes() {
// Associate the unicorn text editor with the "Full HTML" text format.
$editor = entity_create('editor', array(
'format' => 'full_html',
'editor' => 'unicorn',
'image_upload' => array(
'status' => FALSE,
'scheme' => file_default_scheme(),
'directory' => 'inline-images',
'max_size' => '',
'max_dimensions' => array('width' => '', 'height' => ''),
)
));
$editor->save();
// Create an "page" node that uses the full_html text format.
$this->drupalCreateNode(array(
'type' => 'page',
'field_text' => array(
array('value' => $this->randomMachineName(32), 'format' => 'full_html')
),
));
// Assert the unicorn editor works with textfields.
$this->drupalLogin($this->privilegedUser);
$this->drupalGet('node/1/edit');
list( , $editor_settings_present, $editor_js_present, $field, $format_selector) = $this->getThingsToCheck('field-text', 'input');
$this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
$this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
$this->assertTrue(count($field) === 1, 'A text field exists.');
$this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
$specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-field-text-0-value"]');
$this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
// Associate the trex text editor with the "Full HTML" text format.
$editor->delete();
entity_create('editor', array(
'format' => 'full_html',
'editor' => 'trex',
))->save();
$this->drupalGet('node/1/edit');
list( , $editor_settings_present, $editor_js_present, $field, $format_selector) = $this->getThingsToCheck('field-text', 'input');
$this->assertFalse($editor_settings_present, "Text Editor module's JavaScript settings are not on the page.");
$this->assertFalse($editor_js_present, 'Text Editor JavaScript is not present.');
$this->assertTrue(count($field) === 1, 'A text field exists.');
$this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
$specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-field-text-0-value"]');
$this->assertFalse(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
}
protected function getThingsToCheck($field_name, $type = 'textarea') {
$settings = $this->getDrupalSettings();
return array(
// JavaScript settings.
......@@ -193,7 +280,7 @@ protected function getThingsToCheck() {
// Editor.module's JS present.
strpos($this->getRawContent(), drupal_get_path('module', 'editor') . '/js/editor.js') !== FALSE,
// Body field.
$this->xpath('//textarea[@id="edit-body-0-value"]'),
$this->xpath('//' . $type . '[@id="edit-' . $field_name . '-0-value"]'),
// Format selector.
$this->xpath('//select[contains(@class, "filter-list")]'),
);
......
......@@ -7,3 +7,11 @@ editor.settings.unicorn:
ponies_too:
type: boolean
label: 'Ponies too'
editor.settings.trex:
type: mapping
label: 'T-Rex settings'
mapping:
stumpy_arms:
type: boolean
label: 'Stumpy arms'
......@@ -2,3 +2,7 @@ unicorn:
version: VERSION
js:
unicorn.js: {}
trex:
version: VERSION
js:
trex.js: {}
......@@ -35,3 +35,12 @@ function editor_test_editor_xss_filter_alter(&$editor_xss_filter_class, FilterFo
$editor_xss_filter_class = '\Drupal\editor_test\EditorXssFilter\Insecure';
}
}
/**
* Implements hook_editor_info_alter().
*/
function editor_test_editor_info_alter(&$items) {
if (!\Drupal::state()->get('editor_test_give_me_a_trex_thanks', FALSE)) {
unset($items['trex']);
}
}
<?php
/**
* @file
* Contains \Drupal\editor_test\Plugin\Editor\TRexEditor.
*/
namespace Drupal\editor_test\Plugin\Editor;
use Drupal\Core\Form\FormStateInterface;
use Drupal\editor\Plugin\EditorBase;
use Drupal\editor\Entity\Editor as EditorEntity;
/**
* Defines a Tyrannosaurus-Rex powered text editor for testing purposes.
*
* @Editor(
* id = "trex",
* label = @Translation("TRex Editor"),
* supports_content_filtering = TRUE,
* supports_inline_editing = TRUE,
* is_xss_safe = FALSE,
* supported_element_types = {
* "textarea",
* }
* )
*/
class TRexEditor extends EditorBase {
/**
* {@inheritdoc}
*/
public function getDefaultSettings() {
return array('stumpy_arms' => TRUE);
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state, EditorEntity $editor) {
$form['stumpy_arms'] = array(
'#title' => t('Stumpy arms'),
'#type' => 'checkbox',
'#default_value' => TRUE,
);
return $form;
}
/**
* {@inheritdoc}
*/
public function getJSSettings(EditorEntity $editor) {
$js_settings = array();
$settings = $editor->getSettings();
if ($settings['stumpy_arms']) {
$js_settings['doMyArmsLookStumpy'] = TRUE;
}
return $js_settings;
}
/**
* {@inheritdoc}
*/
public function getLibraries(EditorEntity $editor) {
return array(
'editor_test/trex',
);
}
}
......@@ -19,7 +19,11 @@
* label = @Translation("Unicorn Editor"),
* supports_content_filtering = TRUE,
* supports_inline_editing = TRUE,
* is_xss_safe = FALSE
* is_xss_safe = FALSE,
* supported_element_types = {
* "textarea",
* "textfield",
* }
* )
*/
class UnicornEditor extends EditorBase {
......
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