/** * Test access to the editor image dialog. */ public function testEditorImageDialogAccess() { $url = Url::fromRoute('editor.image_dialog', ['editor' => 'plain_text']); $session = $this->assertSession(); // With no text editor, expect a 404. $this->drupalGet($url); $session->statusCodeEquals(404); // With a text editor but without image upload settings, expect a 200, but // there should not be an input[type=file]. $editor = Editor::create(['editor' => 'ckeditor', 'format' => 'plain_text', 'settings' => ['toolbar' => ['rows' => [[['name' => 'Media', 'items' => ['DrupalImage']]]]], 'plugins' => []], 'image_upload' => ['status' => FALSE, 'scheme' => 'public', 'directory' => 'inline-images', 'max_size' => '', 'max_dimensions' => ['width' => 0, 'height' => 0]]]); $editor->save(); $this->resetAll(); $this->drupalGet($url); $this->assertTrue($this->cssSelect('input[type=text][name="attributes[src]"]'), 'Image uploads disabled: input[type=text][name="attributes[src]"] is present.'); $this->assertFalse($this->cssSelect('input[type=file]'), 'Image uploads disabled: input[type=file] is absent.'); $session->statusCodeEquals(200); // With image upload settings, expect a 200, and now there should be an // input[type=file]. $editor->setImageUploadSettings(['status' => TRUE] + $editor->getImageUploadSettings())->save(); $this->resetAll(); $this->drupalGet($url); $this->assertFalse($this->cssSelect('input[type=text][name="attributes[src]"]'), 'Image uploads enabled: input[type=text][name="attributes[src]"] is absent.'); $this->assertTrue($this->cssSelect('input[type=file]'), 'Image uploads enabled: input[type=file] is present.'); $session->statusCodeEquals(200); }
/** * Tests the entity embed button markup. */ public function testEntityEmbedButtonMarkup() { // Ensure that the route is not accessible with text format without the // button configured. $this->getEmbedDialog('plain_text', 'node'); $this->assertResponse(404, 'Embed dialog is not accessible with a filter that does not have an editor configuration.'); // Add an empty configuration for the plain_text editor configuration. $editor = Editor::create(['format' => 'plain_text', 'editor' => 'ckeditor']); $editor->save(); $this->getEmbedDialog('plain_text', 'node'); $this->assertResponse(403, 'Embed dialog is not accessible with a filter that does not have the embed button assigned to it.'); // Ensure that the route is accessible with a valid embed button. // 'Node' embed button is provided by default by the module and hence the // request must be successful. $this->getEmbedDialog('custom_format', 'node'); $this->assertResponse(200, 'Embed dialog is accessible with correct filter format and embed button.'); // Ensure form structure of the 'select' step and submit form. $this->assertFieldByName('attributes[data-entity-id]', '', 'Entity ID/UUID field is present.'); // Check that 'Next' is a primary button. $this->assertFieldByXPath('//input[contains(@class, "button--primary")]', 'Next', 'Next is a primary button'); $title = $this->node->getTitle() . ' (' . $this->node->id() . ')'; $edit = ['attributes[data-entity-id]' => $title]; $this->drupalPostAjaxForm(NULL, $edit, 'op'); /*$this->drupalPostForm(NULL, $edit, 'Next'); // Ensure form structure of the 'embed' step and submit form. $this->assertFieldByName('attributes[data-entity-embed-display]', 'Entity Embed Display plugin field is present.'); // Check that 'Embed' is a primary button. $this->assertFieldByXPath('//input[contains(@class, "button--primary")]', 'Embed', 'Embed is a primary button');*/ }
/** * Ensure comment form works with history and big_pipe modules. * * @see https://www.drupal.org/node/2698811 */ public function testCommentForm_2698811() { $this->assertTrue($this->container->get('module_installer')->install(['comment', 'history', 'ckeditor'], TRUE), 'Installed modules.'); // Ensure an `article` node type exists. $this->createContentType(['type' => 'article']); $this->addDefaultCommentField('node', 'article'); // Enable CKEditor. $format = $this->randomMachineName(); FilterFormat::create(['format' => $format, 'name' => $this->randomString(), 'weight' => 1, 'filters' => []])->save(); $settings['toolbar']['rows'] = [[['name' => 'Links', 'items' => ['DrupalLink', 'DrupalUnlink']]]]; $editor = Editor::create(['format' => $format, 'editor' => 'ckeditor']); $editor->setSettings($settings); $editor->save(); $admin_user = $this->drupalCreateUser(['access comments', 'post comments', 'use text format ' . $format]); $this->drupalLogin($admin_user); $node = $this->createNode(['type' => 'article', 'comment' => CommentItemInterface::OPEN]); // Create some comments. foreach (range(1, 5) as $i) { $comment = Comment::create(['status' => CommentInterface::PUBLISHED, 'field_name' => 'comment', 'entity_type' => 'node', 'entity_id' => $node->id()]); $comment->save(); } $this->drupalGet($node->toUrl()->toString()); // Confirm that CKEditor loaded. $javascript = <<<JS (function(){ return Object.keys(CKEDITOR.instances).length > 0; }()); JS; $this->assertJsCondition($javascript); }
/** * Tests the configurable text editor manager. */ public function testManager() { $this->editorManager = $this->container->get('plugin.manager.editor'); // Case 1: no text editor available: // - listOptions() should return an empty list of options // - getAttachments() should return an empty #attachments array (and not // a JS settings structure that is empty) $this->assertIdentical(array(), $this->editorManager->listOptions(), 'When no text editor is enabled, the manager works correctly.'); $this->assertIdentical(array(), $this->editorManager->getAttachments(array()), 'No attachments when no text editor is enabled and retrieving attachments for zero text formats.'); $this->assertIdentical(array(), $this->editorManager->getAttachments(array('filtered_html', 'full_html')), 'No attachments when no text editor is enabled and retrieving attachments for multiple text formats.'); // Enable the Text Editor Test module, which has the Unicorn Editor and // clear the editor manager's cache so it is picked up. $this->enableModules(array('editor_test')); $this->editorManager = $this->container->get('plugin.manager.editor'); $this->editorManager->clearCachedDefinitions(); // Case 2: a text editor available. $this->assertIdentical('Unicorn Editor', (string) $this->editorManager->listOptions()['unicorn'], 'When some text editor is enabled, the manager works correctly.'); // Case 3: a text editor available & associated (but associated only with // the 'Full HTML' text format). $unicorn_plugin = $this->editorManager->createInstance('unicorn'); $editor = Editor::create(['format' => 'full_html', 'editor' => 'unicorn']); $editor->save(); $this->assertIdentical(array(), $this->editorManager->getAttachments(array()), 'No attachments when one text editor is enabled and retrieving attachments for zero text formats.'); $expected = array('library' => array(0 => 'editor_test/unicorn'), 'drupalSettings' => ['editor' => ['formats' => ['full_html' => ['format' => 'full_html', 'editor' => 'unicorn', 'editorSettings' => $unicorn_plugin->getJSSettings($editor), 'editorSupportsContentFiltering' => TRUE, 'isXssSafe' => FALSE]]]]); $this->assertIdentical($expected, $this->editorManager->getAttachments(array('filtered_html', 'full_html')), 'Correct attachments when one text editor is enabled and retrieving attachments for multiple text formats.'); // Case 4: a text editor available associated, but now with its JS settings // being altered via hook_editor_js_settings_alter(). \Drupal::state()->set('editor_test_js_settings_alter_enabled', TRUE); $expected['drupalSettings']['editor']['formats']['full_html']['editorSettings']['ponyModeEnabled'] = FALSE; $this->assertIdentical($expected, $this->editorManager->getAttachments(array('filtered_html', 'full_html')), 'hook_editor_js_settings_alter() works correctly.'); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); // Create a text format and associate this with CKEditor. FilterFormat::create(['format' => 'full_html', 'name' => 'Full HTML', 'weight' => 1, 'filters' => []])->save(); Editor::create(['format' => 'full_html', 'editor' => 'ckeditor'])->save(); // Create a new user with admin rights. $this->admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages', 'administer site configuration', 'administer filters']); }
protected function setUp() { parent::setUp(); // Install the Filter module. // Create text format, associate CKEditor. $filtered_html_format = FilterFormat::create(array('format' => 'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, 'filters' => array())); $filtered_html_format->save(); $editor = Editor::create(['format' => 'filtered_html', 'editor' => 'ckeditor']); $editor->save(); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $this->format = strtolower($this->randomMachineName()); $filter_format = FilterFormat::create(['format' => $this->format, 'name' => $this->randomString(), 'filters' => []]); $filter_format->save(); $editor = Editor::create(['format' => $this->format, 'editor' => 'ckeditor']); $editor->save(); $this->adminUser = $this->drupalCreateUser(['administer filters']); }
/** * Tests \Drupal\embed\Access\EmbedButtonEditorAccessCheck. */ public function testEmbedButtonEditorAccessCheck() { // The anonymous user should have access to the plain_text format, but it // hasn't been configured to use an editor yet. $this->getRoute('plain_text', 'embed_test_default'); $this->assertResponse(404); $this->assertCacheContext('route'); $this->assertNoCacheTag('config:editor.editor.embed_test'); $this->assertNoCacheTag('config:embed.button.embed_test_default'); // The anonymous user should not have permission to use embed_test format. $this->getRoute('embed_test', 'embed_test_default'); $this->assertResponse(403); $this->assertCacheContext('route'); $this->assertNoCacheTag('config:editor.editor.embed_test'); $this->assertNoCacheTag('config:embed.button.embed_test_default'); // Now login a user that can use the embed_test format. $this->drupalLogin($this->webUser); $this->getRoute('plain_text', 'embed_test_default'); $this->assertResponse(404); $this->assertCacheContext('route'); $this->assertNoCacheTag('config:editor.editor.plain_text'); $this->assertNoCacheTag('config:embed.button.embed_test_default'); // Add an empty configuration for the plain_text editor configuration. $editor = Editor::create(['format' => 'plain_text', 'editor' => 'ckeditor']); $editor->save(); $this->getRoute('plain_text', 'embed_test_default'); $this->assertResponse(403); $this->assertCacheContext('route'); $this->assertCacheTag('config:editor.editor.plain_text'); $this->assertCacheTag('config:embed.button.embed_test_default'); $this->getRoute('embed_test', 'embed_test_default'); $this->assertResponse(200); $this->assertCacheContext('route'); $this->assertCacheTag('config:editor.editor.embed_test'); $this->assertCacheTag('config:embed.button.embed_test_default'); $this->assertText(static::SUCCESS); // Test route with an empty request. $this->getRoute('embed_test', 'embed_test_default', ''); $this->assertResponse(404); $this->assertCacheContext('route'); $this->assertCacheTag('config:editor.editor.embed_test'); $this->assertCacheTag('config:embed.button.embed_test_default'); // Test route with an invalid text format. $this->getRoute('invalid_editor', 'embed_test_default'); $this->assertResponse(404); $this->assertCacheContext('route'); $this->assertNoCacheTag('config:editor.editor.invalid_editor'); $this->assertNoCacheTag('config:embed.button.embed_test_default'); // Test route with an invalid embed button. $this->getRoute('embed_test', 'invalid_button'); $this->assertResponse(404); $this->assertCacheContext('route'); $this->assertNoCacheTag('config:editor.editor.embed_test'); $this->assertNoCacheTag('config:embed.button.invalid_button'); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $this->installEntitySchema('editor'); $this->installEntitySchema('filter_format'); $this->format = FilterFormat::create(['format' => 'test_format', 'name' => $this->randomMachineName()]); $this->format->save(); $this->editor = Editor::create(['editor' => 'ckeditor', 'format' => 'test_format', 'settings' => ['toolbar' => ['rows' => [[['name' => 'Enabled Buttons', 'items' => ['Format']]]]]]]); $this->editor->save(); $this->ckeditorPluginManager = $this->container->get('plugin.manager.ckeditor.plugin'); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); // Add text format. FilterFormat::create(['format' => 'basic_html', 'name' => 'Basic HTML', 'weight' => 0])->save(); // Set up text editor. Editor::create(['format' => 'basic_html', 'editor' => 'unicorn', 'image_upload' => ['status' => TRUE, 'scheme' => 'public', 'directory' => 'inline-images', 'max_size' => '', 'max_dimensions' => ['width' => NULL, 'height' => NULL]]])->save(); // Create admin user. $this->adminUser = $this->drupalCreateUser(['administer filters', 'use text format basic_html']); $this->drupalLogin($this->adminUser); }
protected function setUp() { parent::setUp(); // Install the Filter module. // Create text format, associate CKEditor. $filtered_html_format = FilterFormat::create(array('format' => 'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, 'filters' => array('filter_html' => array('status' => 1, 'settings' => array('allowed_html' => '<h2 id> <h3> <h4> <h5> <h6> <p> <br> <strong> <a href hreflang>'))))); $filtered_html_format->save(); $editor = Editor::create(['format' => 'filtered_html', 'editor' => 'ckeditor']); $editor->save(); // Create "CKEditor" text editor plugin instance. $this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor'); }
protected function setUp() { parent::setUp(); // Install the Filter module. // Create a field. $this->fieldName = 'field_textarea'; $this->createFieldWithStorage($this->fieldName, 'text', 1, 'Long text field', array(), 'text_textarea', array('size' => 42), 'text_default', array()); // Create text format. $full_html_format = FilterFormat::create(array('format' => 'full_html', 'name' => 'Full HTML', 'weight' => 1, 'filters' => array())); $full_html_format->save(); // Associate text editor with text format. $editor = Editor::create(['format' => $full_html_format->id(), 'editor' => 'unicorn']); $editor->save(); // Also create a text format without an associated text editor. FilterFormat::create(array('format' => 'no_editor', 'name' => 'No Text Editor', 'weight' => 2, 'filters' => array()))->save(); }
protected function setUp() { parent::setUp(); // Create text format, associate CKEditor. $filtered_html_format = FilterFormat::create(array('format' => 'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, 'filters' => array())); $filtered_html_format->save(); $editor = Editor::create(['format' => 'filtered_html', 'editor' => 'ckeditor']); $editor->save(); // Create a second format without an associated editor so a drop down select // list is created when selecting formats. $full_html_format = FilterFormat::create(array('format' => 'full_html', 'name' => 'Full HTML', 'weight' => 1, 'filters' => array())); $full_html_format->save(); // Create node type. $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); $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', 'use text format full_html')); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); // Create Filtered HTML text format and enable entity_embed filter. $format = FilterFormat::create(['format' => 'embed_test', 'name' => 'Embed format', 'filters' => []]); $format->save(); $editor_group = ['name' => 'Embed', 'items' => ['embed_test_default']]; $editor = Editor::create(['format' => 'embed_test', 'editor' => 'ckeditor', 'settings' => ['toolbar' => ['rows' => [[$editor_group]]]]]); $editor->save(); // Create a user with required permissions. $this->adminUser = $this->drupalCreateUser(['administer embed buttons', 'use text format embed_test']); // Create a user with required permissions. $this->webUser = $this->drupalCreateUser(['use text format embed_test']); // Set up some standard blocks for the testing theme (Classy). // @see https://www.drupal.org/node/507488?page=1#comment-10291517 $this->drupalPlaceBlock('local_tasks_block'); $this->drupalPlaceBlock('local_actions_block'); }
protected function setUp() { parent::setUp(); $this->installEntitySchema('file'); $this->installSchema('node', array('node_access')); $this->installSchema('file', array('file_usage')); $this->installConfig(['node']); // Add text formats. $filtered_html_format = FilterFormat::create(array('format' => 'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, 'filters' => array())); $filtered_html_format->save(); // Set cardinality for body field. FieldStorageConfig::loadByName('node', 'body')->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)->save(); // Set up text editor. $editor = Editor::create(['format' => 'filtered_html', 'editor' => 'unicorn']); $editor->save(); // Create a node type for testing. $type = NodeType::create(['type' => 'page', 'name' => 'page']); $type->save(); node_add_body_field($type); }
/** * Sets up the test. */ protected function setUp() { parent::setUp(); $this->installEntitySchema('file'); $this->installSchema('system', ['key_value_expire']); $this->installSchema('node', array('node_access')); $this->installSchema('file', array('file_usage')); $this->installConfig(['node']); // Add text formats. $this->format = FilterFormat::create(['format' => 'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, 'filters' => ['filter_align' => ['status' => TRUE], 'filter_caption' => ['status' => TRUE]]]); $this->format->save(); // Set up text editor. $editor = Editor::create(['format' => 'filtered_html', 'editor' => 'unicorn', 'image_upload' => ['max_size' => 100, 'scheme' => 'public', 'directory' => '', 'status' => TRUE]]); $editor->save(); // Create a node type for testing. $type = NodeType::create(['type' => 'page', 'name' => 'page']); $type->save(); node_add_body_field($type); $this->installEntitySchema('user'); \Drupal::service('router.builder')->rebuild(); }
/** * Tests text format removal or disabling. */ public function testTextFormatIntegration() { // Create an arbitrary text format. $format = FilterFormat::create(['format' => Unicode::strtolower($this->randomMachineName()), 'name' => $this->randomString()]); $format->save(); // Create a paired editor. Editor::create(['format' => $format->id(), 'editor' => 'unicorn'])->save(); // Disable the text format. $format->disable()->save(); // The paired editor should be disabled too. $this->assertFalse(Editor::load($format->id())->status()); // Re-enable the text format. $format->enable()->save(); // The paired editor should be enabled too. $this->assertTrue(Editor::load($format->id())->status()); // Completely remove the text format. Usually this cannot occur via UI, but // can be triggered from API. $format->delete(); // The paired editor should be removed. $this->assertNull(Editor::load($format->id())); }
protected function setUp() { parent::setUp(); // Create a page content type. $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); // Create a text format and enable the entity_embed filter. $format = FilterFormat::create(['format' => 'custom_format', 'name' => 'Custom format', 'filters' => ['entity_embed' => ['status' => 1]]]); $format->save(); $editor_group = ['name' => 'Entity Embed', 'items' => ['node']]; $editor = Editor::create(['format' => 'custom_format', 'editor' => 'ckeditor', 'settings' => ['toolbar' => ['rows' => [[$editor_group]]]]]); $editor->save(); // Create a user with required permissions. $this->webUser = $this->drupalCreateUser(['access content', 'create page content', 'use text format custom_format']); $this->drupalLogin($this->webUser); // Create a sample node to be embedded. $settings = array(); $settings['type'] = 'page'; $settings['title'] = 'Embed Test Node'; $settings['body'] = array('value' => 'This node is to be used for embedding in other nodes.', 'format' => 'custom_format'); $this->node = $this->drupalCreateNode($settings); }
protected function setUp() { parent::setUp(); // Create 5 text formats, to cover all potential use cases: // 1. restricted_without_editor (untrusted: anonymous) // 2. restricted_with_editor (normal: authenticated) // 3. restricted_plus_dangerous_tag_with_editor (privileged: trusted) // 4. unrestricted_without_editor (privileged: admin) // 5. unrestricted_with_editor (privileged: admin) // With text formats 2, 3 and 5, we also associate a text editor that does // not guarantee XSS safety. "restricted" means the text format has XSS // filters on output, "unrestricted" means the opposite. $format = FilterFormat::create(array('format' => 'restricted_without_editor', 'name' => 'Restricted HTML, without text editor', 'weight' => 0, 'filters' => array('filter_html' => array('status' => 1, 'settings' => array('allowed_html' => '<h2> <h3> <h4> <h5> <h6> <p> <br> <strong> <a>'))))); $format->save(); $format = FilterFormat::create(array('format' => 'restricted_with_editor', 'name' => 'Restricted HTML, with text editor', 'weight' => 1, 'filters' => array('filter_html' => array('status' => 1, 'settings' => array('allowed_html' => '<h2> <h3> <h4> <h5> <h6> <p> <br> <strong> <a>'))))); $format->save(); $editor = Editor::create(['format' => 'restricted_with_editor', 'editor' => 'unicorn']); $editor->save(); $format = FilterFormat::create(array('format' => 'restricted_plus_dangerous_tag_with_editor', 'name' => 'Restricted HTML, dangerous tag allowed, with text editor', 'weight' => 1, 'filters' => array('filter_html' => array('status' => 1, 'settings' => array('allowed_html' => '<h2> <h3> <h4> <h5> <h6> <p> <br> <strong> <a> <embed>'))))); $format->save(); $editor = Editor::create(['format' => 'restricted_plus_dangerous_tag_with_editor', 'editor' => 'unicorn']); $editor->save(); $format = FilterFormat::create(array('format' => 'unrestricted_without_editor', 'name' => 'Unrestricted HTML, without text editor', 'weight' => 0, 'filters' => array())); $format->save(); $format = FilterFormat::create(array('format' => 'unrestricted_with_editor', 'name' => 'Unrestricted HTML, with text editor', 'weight' => 1, 'filters' => array())); $format->save(); $editor = Editor::create(['format' => 'unrestricted_with_editor', 'editor' => 'unicorn']); $editor->save(); // Create node type. $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); // Create 4 users, each with access to different text formats/editors: // - "untrusted": restricted_without_editor // - "normal": restricted_with_editor, // - "trusted": restricted_plus_dangerous_tag_with_editor // - "privileged": restricted_without_editor, restricted_with_editor, // restricted_plus_dangerous_tag_with_editor, // unrestricted_without_editor and unrestricted_with_editor $this->untrustedUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format restricted_without_editor')); $this->normalUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format restricted_with_editor')); $this->trustedUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format restricted_plus_dangerous_tag_with_editor')); $this->privilegedUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format restricted_without_editor', 'use text format restricted_with_editor', 'use text format restricted_plus_dangerous_tag_with_editor', 'use text format unrestricted_without_editor', 'use text format unrestricted_with_editor')); // Create an "article" node for each possible text format, with the same // sample content, to do our tests on. $samples = array(array('author' => $this->untrustedUser->id(), 'format' => 'restricted_without_editor'), array('author' => $this->normalUser->id(), 'format' => 'restricted_with_editor'), array('author' => $this->trustedUser->id(), 'format' => 'restricted_plus_dangerous_tag_with_editor'), array('author' => $this->privilegedUser->id(), 'format' => 'unrestricted_without_editor'), array('author' => $this->privilegedUser->id(), 'format' => 'unrestricted_with_editor')); foreach ($samples as $sample) { $this->drupalCreateNode(array('type' => 'article', 'body' => array(array('value' => self::$sampleContent, 'format' => $sample['format'])), 'uid' => $sample['author'])); } }
/** * Test supported element types. */ public function testSupportedElementTypes() { // Associate the unicorn text editor with the "Full HTML" text format. $editor = Editor::create(['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(); Editor::create(['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.'); }
/** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) { $settings = $editor->getSettings(); $ckeditor_settings_toolbar = array('#theme' => 'ckeditor_settings_toolbar', '#editor' => $editor, '#plugins' => $this->ckeditorPluginManager->getButtons()); $form['toolbar'] = array('#type' => 'container', '#attached' => array('library' => array('ckeditor/drupal.ckeditor.admin'), 'drupalSettings' => ['ckeditor' => ['toolbarAdmin' => (string) $this->renderer->renderPlain($ckeditor_settings_toolbar)]]), '#attributes' => array('class' => array('ckeditor-toolbar-configuration'))); $form['toolbar']['button_groups'] = array('#type' => 'textarea', '#title' => t('Toolbar buttons'), '#default_value' => json_encode($settings['toolbar']['rows']), '#attributes' => array('class' => array('ckeditor-toolbar-textarea'))); // CKEditor plugin settings, if any. $form['plugin_settings'] = array('#type' => 'vertical_tabs', '#title' => t('CKEditor plugin settings'), '#attributes' => array('id' => 'ckeditor-plugin-settings')); $this->ckeditorPluginManager->injectPluginSettingsForm($form, $form_state, $editor); if (count(Element::children($form['plugins'])) === 0) { unset($form['plugins']); unset($form['plugin_settings']); } // Hidden CKEditor instance. We need a hidden CKEditor instance with all // plugins enabled, so we can retrieve CKEditor's per-feature metadata (on // which tags, attributes, styles and classes are enabled). This metadata is // necessary for certain filters' (for instance, the html_filter filter) // settings to be updated accordingly. // Get a list of all external plugins and their corresponding files. $plugins = array_keys($this->ckeditorPluginManager->getDefinitions()); $all_external_plugins = array(); foreach ($plugins as $plugin_id) { $plugin = $this->ckeditorPluginManager->createInstance($plugin_id); if (!$plugin->isInternal()) { $all_external_plugins[$plugin_id] = $plugin->getFile(); } } // Get a list of all buttons that are provided by all plugins. $all_buttons = array_reduce($this->ckeditorPluginManager->getButtons(), function ($result, $item) { return array_merge($result, array_keys($item)); }, array()); // Build a fake Editor object, which we'll use to generate JavaScript // settings for this fake Editor instance. $fake_editor = Editor::create(array('format' => $editor->id(), 'editor' => 'ckeditor', 'settings' => array('toolbar' => array('rows' => array(0 => array(0 => array('name' => 'All existing buttons', 'items' => $all_buttons)))), 'plugins' => $settings['plugins']))); $config = $this->getJSSettings($fake_editor); // Remove the ACF configuration that is generated based on filter settings, // because otherwise we cannot retrieve per-feature metadata. unset($config['allowedContent']); $form['hidden_ckeditor'] = array('#markup' => '<div id="ckeditor-hidden" class="hidden"></div>', '#attached' => array('drupalSettings' => ['ckeditor' => ['hiddenCKEditorConfig' => $config]])); return $form; }
/** * Tests configuring a text editor for an existing text format. */ function testExistingFormat() { $ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor'); $this->drupalLogin($this->adminUser); $this->drupalGet('admin/config/content/formats/manage/filtered_html'); // Ensure no Editor config entity exists yet. $editor = entity_load('editor', 'filtered_html'); $this->assertFalse($editor, 'No Editor config entity exists yet.'); // Verify the "Text Editor" <select> when a text editor is available. $select = $this->xpath('//select[@name="editor[editor]"]'); $select_is_disabled = $this->xpath('//select[@name="editor[editor]" and @disabled="disabled"]'); $options = $this->xpath('//select[@name="editor[editor]"]/option'); $this->assertTrue(count($select) === 1, 'The Text Editor select exists.'); $this->assertTrue(count($select_is_disabled) === 0, 'The Text Editor select is not disabled.'); $this->assertTrue(count($options) === 2, 'The Text Editor select has two options.'); $this->assertTrue((string) $options[0] === 'None', 'Option 1 in the Text Editor select is "None".'); $this->assertTrue((string) $options[1] === 'CKEditor', 'Option 2 in the Text Editor select is "CKEditor".'); $this->assertTrue((string) $options[0]['selected'] === 'selected', 'Option 1 ("None") is selected.'); // Select the "CKEditor" editor and click the "Save configuration" button. $edit = array('editor[editor]' => 'ckeditor'); $this->drupalPostForm(NULL, $edit, t('Save configuration')); $this->assertRaw(t('You must configure the selected text editor.')); // Ensure the CKEditor editor returns the expected default settings. $expected_default_settings = array('toolbar' => array('rows' => array(array(array('name' => 'Formatting', 'items' => array('Bold', 'Italic')), array('name' => 'Links', 'items' => array('DrupalLink', 'DrupalUnlink')), array('name' => 'Lists', 'items' => array('BulletedList', 'NumberedList')), array('name' => 'Media', 'items' => array('Blockquote', 'DrupalImage')), array('name' => 'Tools', 'items' => array('Source'))))), 'plugins' => ['language' => ['language_list' => 'un']]); $this->assertIdentical($this->castSafeStrings($ckeditor->getDefaultSettings()), $expected_default_settings); // Keep the "CKEditor" editor selected and click the "Configure" button. $this->drupalPostAjaxForm(NULL, $edit, 'editor_configure'); $editor = entity_load('editor', 'filtered_html'); $this->assertFalse($editor, 'No Editor config entity exists yet.'); // Ensure that drupalSettings is correct. $ckeditor_settings_toolbar = array('#theme' => 'ckeditor_settings_toolbar', '#editor' => Editor::create(['editor' => 'ckeditor']), '#plugins' => $this->container->get('plugin.manager.ckeditor.plugin')->getButtons()); $this->assertEqual($this->drupalSettings['ckeditor']['toolbarAdmin'], $this->container->get('renderer')->renderPlain($ckeditor_settings_toolbar), 'CKEditor toolbar settings are rendered as part of drupalSettings.'); // Ensure the toolbar buttons configuration value is initialized to the // expected default value. $expected_buttons_value = json_encode($expected_default_settings['toolbar']['rows']); $this->assertFieldByName('editor[settings][toolbar][button_groups]', $expected_buttons_value); // Ensure the styles textarea exists and is initialized empty. $styles_textarea = $this->xpath('//textarea[@name="editor[settings][plugins][stylescombo][styles]"]'); $this->assertFieldByXPath('//textarea[@name="editor[settings][plugins][stylescombo][styles]"]', '', 'The styles textarea exists and is empty.'); $this->assertTrue(count($styles_textarea) === 1, 'The "styles" textarea exists.'); // Submit the form to save the selection of CKEditor as the chosen editor. $this->drupalPostForm(NULL, $edit, t('Save configuration')); // Ensure an Editor object exists now, with the proper settings. $expected_settings = $expected_default_settings; $expected_settings['plugins']['stylescombo']['styles'] = ''; $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists now.'); $this->assertEqual($expected_settings, $editor->getSettings(), 'The Editor config entity has the correct settings.'); // Configure the Styles plugin, and ensure the updated settings are saved. $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $edit = array('editor[settings][plugins][stylescombo][styles]' => "h1.title|Title\np.callout|Callout\n\n"); $this->drupalPostForm(NULL, $edit, t('Save configuration')); $expected_settings['plugins']['stylescombo']['styles'] = "h1.title|Title\np.callout|Callout\n\n"; $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists.'); $this->assertEqual($expected_settings, $editor->getSettings(), 'The Editor config entity has the correct settings.'); // Change the buttons that appear on the toolbar (in JavaScript, this is // done via drag and drop, but here we can only emulate the end result of // that interaction). Test multiple toolbar rows and a divider within a row. $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $expected_settings['toolbar']['rows'][0][] = array('name' => 'Action history', 'items' => array('Undo', '|', 'Redo', 'JustifyCenter')); $edit = array('editor[settings][toolbar][button_groups]' => json_encode($expected_settings['toolbar']['rows'])); $this->drupalPostForm(NULL, $edit, t('Save configuration')); $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists.'); $this->assertEqual($expected_settings, $editor->getSettings(), 'The Editor config entity has the correct settings.'); // Check that the markup we're setting for the toolbar buttons (actually in // JavaScript's drupalSettings, and Unicode-escaped) is correctly rendered. $this->drupalGet('admin/config/content/formats/manage/filtered_html'); // Create function to encode HTML as we expect it in drupalSettings. $json_encode = function ($html) { return trim(Json::encode($html), '"'); }; // Check the Button separator. $this->assertRaw($json_encode('<li data-drupal-ckeditor-button-name="-" class="ckeditor-button-separator ckeditor-multiple-button" data-drupal-ckeditor-type="separator"><a href="#" role="button" aria-label="Button separator" class="ckeditor-separator"></a></li>')); // Check the Format dropdown. $this->assertRaw($json_encode('<li data-drupal-ckeditor-button-name="Format" class="ckeditor-button"><a href="#" role="button" aria-label="Format"><span class="ckeditor-button-dropdown">Format<span class="ckeditor-button-arrow"></span></span></a></li>')); // Check the Styles dropdown. $this->assertRaw($json_encode('<li data-drupal-ckeditor-button-name="Styles" class="ckeditor-button"><a href="#" role="button" aria-label="Styles"><span class="ckeditor-button-dropdown">Styles<span class="ckeditor-button-arrow"></span></span></a></li>')); // Check strikethrough. $this->assertRaw($json_encode('<li data-drupal-ckeditor-button-name="Strike" class="ckeditor-button"><a href="#" class="cke-icon-only cke_ltr" role="button" title="strike" aria-label="strike"><span class="cke_button_icon cke_button__strike_icon">strike</span></a></li>')); // Now enable the ckeditor_test module, which provides one configurable // CKEditor plugin — this should not affect the Editor config entity. \Drupal::service('module_installer')->install(array('ckeditor_test')); $this->resetAll(); $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions(); $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $ultra_llama_mode_checkbox = $this->xpath('//input[@type="checkbox" and @name="editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]" and not(@checked)]'); $this->assertTrue(count($ultra_llama_mode_checkbox) === 1, 'The "Ultra llama mode" checkbox exists and is not checked.'); $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists.'); $this->assertEqual($expected_settings, $editor->getSettings(), 'The Editor config entity has the correct settings.'); // Finally, check the "Ultra llama mode" checkbox. $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $edit = array('editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]' => '1'); $this->drupalPostForm(NULL, $edit, t('Save configuration')); $this->drupalGet('admin/config/content/formats/manage/filtered_html'); $ultra_llama_mode_checkbox = $this->xpath('//input[@type="checkbox" and @name="editor[settings][plugins][llama_contextual_and_button][ultra_llama_mode]" and @checked="checked"]'); $this->assertTrue(count($ultra_llama_mode_checkbox) === 1, 'The "Ultra llama mode" checkbox exists and is checked.'); $expected_settings['plugins']['llama_contextual_and_button']['ultra_llama_mode'] = TRUE; $editor = entity_load('editor', 'filtered_html'); $this->assertTrue($editor instanceof Editor, 'An Editor config entity exists.'); $this->assertEqual($expected_settings, $editor->getSettings()); }