1<?php 2 3namespace Drupal\Tests\editor\Kernel; 4 5use Drupal\Component\Serialization\Json; 6use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; 7use Drupal\Core\Language\LanguageInterface; 8use Drupal\editor\Entity\Editor; 9use Drupal\entity_test\Entity\EntityTest; 10use Drupal\quickedit\MetadataGenerator; 11use Drupal\Tests\quickedit\Kernel\QuickEditTestBase; 12use Drupal\quickedit_test\MockQuickEditEntityFieldAccessCheck; 13use Drupal\editor\EditorController; 14use Symfony\Component\HttpFoundation\Request; 15use Symfony\Component\HttpKernel\Event\FilterResponseEvent; 16use Symfony\Component\HttpKernel\HttpKernelInterface; 17use Drupal\filter\Entity\FilterFormat; 18 19/** 20 * Tests Edit module integration (Editor module's inline editing support). 21 * 22 * @group editor 23 */ 24class QuickEditIntegrationTest extends QuickEditTestBase { 25 26 /** 27 * {@inheritdoc} 28 */ 29 public static $modules = ['editor', 'editor_test']; 30 31 /** 32 * The manager for editor plug-ins. 33 * 34 * @var \Drupal\Component\Plugin\PluginManagerInterface 35 */ 36 protected $editorManager; 37 38 /** 39 * The metadata generator object to be tested. 40 * 41 * @var \Drupal\quickedit\MetadataGeneratorInterface 42 */ 43 protected $metadataGenerator; 44 45 /** 46 * The editor selector object to be used by the metadata generator object. 47 * 48 * @var \Drupal\quickedit\EditorSelectorInterface 49 */ 50 protected $editorSelector; 51 52 /** 53 * The access checker object to be used by the metadata generator object. 54 * 55 * @var \Drupal\quickedit\Access\QuickEditEntityFieldAccessCheckInterface 56 */ 57 protected $accessChecker; 58 59 /** 60 * The name of the field ued for tests. 61 * 62 * @var string 63 */ 64 protected $fieldName; 65 66 protected function setUp() { 67 parent::setUp(); 68 69 // Install the Filter module. 70 71 // Create a field. 72 $this->fieldName = 'field_textarea'; 73 $this->createFieldWithStorage( 74 $this->fieldName, 'text', 1, 'Long text field', 75 // Instance settings. 76 [], 77 // Widget type & settings. 78 'text_textarea', 79 ['size' => 42], 80 // 'default' formatter type & settings. 81 'text_default', 82 [] 83 ); 84 85 // Create text format. 86 $full_html_format = FilterFormat::create([ 87 'format' => 'full_html', 88 'name' => 'Full HTML', 89 'weight' => 1, 90 'filters' => [], 91 ]); 92 $full_html_format->save(); 93 94 // Associate text editor with text format. 95 $editor = Editor::create([ 96 'format' => $full_html_format->id(), 97 'editor' => 'unicorn', 98 ]); 99 $editor->save(); 100 101 // Also create a text format without an associated text editor. 102 FilterFormat::create([ 103 'format' => 'no_editor', 104 'name' => 'No Text Editor', 105 'weight' => 2, 106 'filters' => [], 107 ])->save(); 108 } 109 110 /** 111 * Returns the in-place editor that quickedit selects. 112 * 113 * @param int $entity_id 114 * An entity ID. 115 * @param string $field_name 116 * A field name. 117 * @param string $view_mode 118 * A view mode. 119 * 120 * @return string 121 * Returns the selected in-place editor. 122 */ 123 protected function getSelectedEditor($entity_id, $field_name, $view_mode = 'default') { 124 $storage = $this->container->get('entity_type.manager')->getStorage('entity_test'); 125 $storage->resetCache([$entity_id]); 126 $entity = $storage->load($entity_id); 127 $items = $entity->get($field_name); 128 $options = \Drupal::service('entity_display.repository') 129 ->getViewDisplay('entity_test', 'entity_test', $view_mode) 130 ->getComponent($field_name); 131 return $this->editorSelector->getEditor($options['type'], $items); 132 } 133 134 /** 135 * Tests editor selection when the Editor module is present. 136 * 137 * Tests a textual field, with text filtering, with cardinality 1 and >1, 138 * always with a ProcessedTextEditor plug-in present, but with varying text 139 * format compatibility. 140 */ 141 public function testEditorSelection() { 142 $this->editorManager = $this->container->get('plugin.manager.quickedit.editor'); 143 $this->editorSelector = $this->container->get('quickedit.editor.selector'); 144 145 // Create an entity with values for this text field. 146 $entity = EntityTest::create(); 147 $entity->{$this->fieldName}->value = 'Hello, world!'; 148 $entity->{$this->fieldName}->format = 'filtered_html'; 149 $entity->save(); 150 151 // Editor selection w/ cardinality 1, text format w/o associated text editor. 152 $this->assertEqual('form', $this->getSelectedEditor($entity->id(), $this->fieldName), "With cardinality 1, and the filtered_html text format, the 'form' editor is selected."); 153 154 // Editor selection w/ cardinality 1, text format w/ associated text editor. 155 $entity->{$this->fieldName}->format = 'full_html'; 156 $entity->save(); 157 $this->assertEqual('editor', $this->getSelectedEditor($entity->id(), $this->fieldName), "With cardinality 1, and the full_html text format, the 'editor' editor is selected."); 158 159 // Editor selection with text processing, cardinality >1 160 $this->fields->field_textarea_field_storage->setCardinality(2); 161 $this->fields->field_textarea_field_storage->save(); 162 $this->assertEqual('form', $this->getSelectedEditor($entity->id(), $this->fieldName), "With cardinality >1, and both items using the full_html text format, the 'form' editor is selected."); 163 } 164 165 /** 166 * Tests (custom) metadata when the formatted text editor is used. 167 */ 168 public function testMetadata() { 169 $this->editorManager = $this->container->get('plugin.manager.quickedit.editor'); 170 $this->accessChecker = new MockQuickEditEntityFieldAccessCheck(); 171 $this->editorSelector = $this->container->get('quickedit.editor.selector'); 172 $this->metadataGenerator = new MetadataGenerator($this->accessChecker, $this->editorSelector, $this->editorManager); 173 174 // Create an entity with values for the field. 175 $entity = EntityTest::create(); 176 $entity->{$this->fieldName}->value = 'Test'; 177 $entity->{$this->fieldName}->format = 'full_html'; 178 $entity->save(); 179 $entity = EntityTest::load($entity->id()); 180 181 // Verify metadata. 182 $items = $entity->get($this->fieldName); 183 \Drupal::state()->set('quickedit_test_field_access', 'forbidden'); 184 $this->assertSame(['access' => FALSE], $this->metadataGenerator->generateFieldMetadata($items, 'default')); 185 \Drupal::state()->set('quickedit_test_field_access', 'neutral'); 186 $this->assertSame(['access' => FALSE], $this->metadataGenerator->generateFieldMetadata($items, 'default')); 187 \Drupal::state()->set('quickedit_test_field_access', 'allowed'); 188 $metadata = $this->metadataGenerator->generateFieldMetadata($items, 'default'); 189 $expected = [ 190 'access' => TRUE, 191 'label' => 'Long text field', 192 'editor' => 'editor', 193 'custom' => [ 194 'format' => 'full_html', 195 'formatHasTransformations' => FALSE, 196 ], 197 ]; 198 $this->assertEqual($expected, $metadata, 'The correct metadata (including custom metadata) is generated.'); 199 } 200 201 /** 202 * Tests in-place editor attachments when the Editor module is present. 203 */ 204 public function testAttachments() { 205 $this->editorSelector = $this->container->get('quickedit.editor.selector'); 206 207 $editors = ['editor']; 208 $attachments = $this->editorSelector->getEditorAttachments($editors); 209 $this->assertIdentical($attachments, ['library' => ['editor/quickedit.inPlaceEditor.formattedText']], "Expected attachments for Editor module's in-place editor found."); 210 } 211 212 /** 213 * Tests GetUntransformedTextCommand AJAX command. 214 */ 215 public function testGetUntransformedTextCommand() { 216 // Create an entity with values for the field. 217 $entity = EntityTest::create(); 218 $entity->{$this->fieldName}->value = 'Test'; 219 $entity->{$this->fieldName}->format = 'full_html'; 220 $entity->save(); 221 $entity = EntityTest::load($entity->id()); 222 223 // Verify AJAX response. 224 $controller = new EditorController(); 225 $request = new Request(); 226 $response = $controller->getUntransformedText($entity, $this->fieldName, LanguageInterface::LANGCODE_DEFAULT, 'default'); 227 $expected = [ 228 [ 229 'command' => 'editorGetUntransformedText', 230 'data' => 'Test', 231 ], 232 ]; 233 234 $ajax_response_attachments_processor = \Drupal::service('ajax_response.attachments_processor'); 235 $subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor); 236 $event = new FilterResponseEvent( 237 \Drupal::service('http_kernel'), 238 $request, 239 HttpKernelInterface::MASTER_REQUEST, 240 $response 241 ); 242 $subscriber->onResponse($event); 243 244 $this->assertEqual(Json::encode($expected), $response->getContent(), 'The GetUntransformedTextCommand AJAX command works correctly.'); 245 } 246 247} 248