annotate core/modules/editor/src/Element.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\editor;
Chris@0 4
Chris@0 5 use Drupal\editor\Entity\Editor;
Chris@0 6 use Drupal\filter\Entity\FilterFormat;
Chris@0 7 use Drupal\Component\Plugin\PluginManagerInterface;
Chris@0 8 use Drupal\Core\Render\BubbleableMetadata;
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Defines a service for Text Editor's render elements.
Chris@0 12 */
Chris@0 13 class Element {
Chris@0 14
Chris@0 15 /**
Chris@0 16 * The Text Editor plugin manager service.
Chris@0 17 *
Chris@0 18 * @var \Drupal\Component\Plugin\PluginManagerInterface
Chris@0 19 */
Chris@0 20 protected $pluginManager;
Chris@0 21
Chris@0 22 /**
Chris@0 23 * Constructs a new Element object.
Chris@0 24 *
Chris@0 25 * @param \Drupal\Component\Plugin\PluginManagerInterface $plugin_manager
Chris@0 26 * The Text Editor plugin manager service.
Chris@0 27 */
Chris@0 28 public function __construct(PluginManagerInterface $plugin_manager) {
Chris@0 29 $this->pluginManager = $plugin_manager;
Chris@0 30 }
Chris@0 31
Chris@0 32 /**
Chris@0 33 * Additional #pre_render callback for 'text_format' elements.
Chris@0 34 */
Chris@0 35 public function preRenderTextFormat(array $element) {
Chris@0 36 // Allow modules to programmatically enforce no client-side editor by
Chris@0 37 // setting the #editor property to FALSE.
Chris@0 38 if (isset($element['#editor']) && !$element['#editor']) {
Chris@0 39 return $element;
Chris@0 40 }
Chris@0 41
Chris@0 42 // filter_process_format() copies properties to the expanded 'value' child
Chris@0 43 // element, including the #pre_render property. Skip this text format
Chris@0 44 // widget, if it contains no 'format'.
Chris@0 45 if (!isset($element['format'])) {
Chris@0 46 return $element;
Chris@0 47 }
Chris@0 48 $format_ids = array_keys($element['format']['format']['#options']);
Chris@0 49
Chris@0 50 // Early-return if no text editor is associated with any of the text formats.
Chris@0 51 $editors = Editor::loadMultiple($format_ids);
Chris@0 52 foreach ($editors as $key => $editor) {
Chris@0 53 $definition = $this->pluginManager->getDefinition($editor->getEditor());
Chris@0 54 if (!in_array($element['#base_type'], $definition['supported_element_types'])) {
Chris@0 55 unset($editors[$key]);
Chris@0 56 }
Chris@0 57 }
Chris@0 58 if (count($editors) === 0) {
Chris@0 59 return $element;
Chris@0 60 }
Chris@0 61
Chris@0 62 // Use a hidden element for a single text format.
Chris@0 63 $field_id = $element['value']['#id'];
Chris@0 64 if (!$element['format']['format']['#access']) {
Chris@0 65 // Use the first (and only) available text format.
Chris@0 66 $format_id = $format_ids[0];
Chris@0 67 $element['format']['editor'] = [
Chris@0 68 '#type' => 'hidden',
Chris@0 69 '#name' => $element['format']['format']['#name'],
Chris@0 70 '#value' => $format_id,
Chris@0 71 '#attributes' => [
Chris@0 72 'data-editor-for' => $field_id,
Chris@0 73 ],
Chris@0 74 ];
Chris@0 75 }
Chris@0 76 // Otherwise, attach to text format selector.
Chris@0 77 else {
Chris@0 78 $element['format']['format']['#attributes']['class'][] = 'editor';
Chris@0 79 $element['format']['format']['#attributes']['data-editor-for'] = $field_id;
Chris@0 80 }
Chris@0 81
Chris@0 82 // Hide the text format's filters' guidelines of those text formats that have
Chris@0 83 // a text editor associated: they're rather useless when using a text editor.
Chris@0 84 foreach ($editors as $format_id => $editor) {
Chris@0 85 $element['format']['guidelines'][$format_id]['#access'] = FALSE;
Chris@0 86 }
Chris@0 87
Chris@0 88 // Attach Text Editor module's (this module) library.
Chris@0 89 $element['#attached']['library'][] = 'editor/drupal.editor';
Chris@0 90
Chris@0 91 // Attach attachments for all available editors.
Chris@0 92 $element['#attached'] = BubbleableMetadata::mergeAttachments($element['#attached'], $this->pluginManager->getAttachments($format_ids));
Chris@0 93
Chris@0 94 // Apply XSS filters when editing content if necessary. Some types of text
Chris@0 95 // editors cannot guarantee that the end user won't become a victim of XSS.
Chris@0 96 if (!empty($element['value']['#value'])) {
Chris@0 97 $original = $element['value']['#value'];
Chris@0 98 $format = FilterFormat::load($element['format']['format']['#value']);
Chris@0 99
Chris@0 100 // Ensure XSS-safety for the current text format/editor.
Chris@0 101 $filtered = editor_filter_xss($original, $format);
Chris@0 102 if ($filtered !== FALSE) {
Chris@0 103 $element['value']['#value'] = $filtered;
Chris@0 104 }
Chris@0 105
Chris@0 106 // Only when the user has access to multiple text formats, we must add data-
Chris@0 107 // attributes for the original value and change tracking, because they are
Chris@0 108 // only necessary when the end user can switch between text formats/editors.
Chris@0 109 if ($element['format']['format']['#access']) {
Chris@0 110 $element['value']['#attributes']['data-editor-value-is-changed'] = 'false';
Chris@0 111 $element['value']['#attributes']['data-editor-value-original'] = $original;
Chris@0 112 }
Chris@0 113 }
Chris@0 114
Chris@0 115 return $element;
Chris@0 116 }
Chris@0 117
Chris@0 118 }