core/includes/entity.api.php | 12 ++
core/modules/ckeditor/ckeditor.module | 2 -
.../ckeditor/js/ckeditor.drupalimage.admin.js | 9 +-
.../ckeditor/js/plugins/drupalimage/plugin.js | 6 -
.../ckeditor/Plugin/CKEditorPlugin/DrupalImage.php | 112 +++---------
.../modules/editor/config/schema/editor.schema.yml | 26 +++
core/modules/editor/editor.admin.inc | 131 ++++++++++++++
core/modules/editor/editor.module | 188 +++++++++++++++++++-
.../lib/Drupal/editor/Form/EditorImageDialog.php | 25 ++-
.../Drupal/editor/Plugin/Core/Entity/Editor.php | 9 +-
.../text/Plugin/field/widget/TextareaWidget.php | 3 -
.../modules/text/lib/Drupal/text/TextProcessed.php | 41 +----
.../lib/Drupal/views/Plugin/views/area/Text.php | 2 +-
.../Plugin/views/exposed_form/InputRequired.php | 2 +-
.../standard/config/editor.editor.basic_html.yml | 8 +
.../standard/config/editor.editor.full_html.yml | 8 +
16 files changed, 413 insertions(+), 171 deletions(-)
diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php
index 8b97b74..6018c2e 100644
--- a/core/includes/entity.api.php
+++ b/core/includes/entity.api.php
@@ -315,6 +315,18 @@ function hook_entity_delete(Drupal\Core\Entity\EntityInterface $entity) {
}
/**
+ * Respond to entity revision deletion.
+ *
+ * This hook runs after the entity type-specific revision delete hook.
+ *
+ * @param Drupal\Core\Entity\EntityInterface $entity
+ * The entity object for the entity revision that has been deleted.
+ */
+function hook_entity_revision_delete(Drupal\Core\Entity\EntityInterface $entity) {
+ // @todo: code example
+}
+
+/**
* Alter or execute an Drupal\Core\Entity\Query\EntityQueryInterface.
*
* @param \Drupal\Core\Entity\Query\QueryInterface $query
diff --git a/core/modules/ckeditor/ckeditor.module b/core/modules/ckeditor/ckeditor.module
index c03facb..8b587c7 100644
--- a/core/modules/ckeditor/ckeditor.module
+++ b/core/modules/ckeditor/ckeditor.module
@@ -81,8 +81,6 @@ function ckeditor_library_info() {
array('system', 'jquery.once'),
array('system', 'drupal.vertical-tabs'),
array('system', 'drupalSettings'),
- // @todo D8 formUpdated event should be debounced already.
- array('system', 'drupal.debounce'),
),
);
$libraries['ckeditor'] = array(
diff --git a/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js b/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js
index 01d01c7..da0d7e8 100644
--- a/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js
+++ b/core/modules/ckeditor/js/ckeditor.drupalimage.admin.js
@@ -38,10 +38,11 @@ Drupal.behaviors.ckeditorDrupalImageSettings = {
Drupal.behaviors.ckeditorDrupalImageSettingsSummary = {
attach: function () {
$('#edit-editor-settings-plugins-drupalimage').drupalSetSummary(function (context) {
- var $maxFileSize = $('input[name="editor[settings][plugins][drupalimage][max_size]"]');
- var $maxWidth = $('input[name="editor[settings][plugins][drupalimage][max_dimensions][width]"]');
- var $maxHeight = $('input[name="editor[settings][plugins][drupalimage][max_dimensions][height]"]');
- var $scheme = $('input[name="editor[settings][plugins][drupalimage][scheme]"]:checked');
+ var root = 'input[name="editor[settings][plugins][drupalimage][image_upload]';
+ var $maxFileSize = $(root + '[max_size]"]');
+ var $maxWidth = $(root + '[max_dimensions][width]"]');
+ var $maxHeight = $(root + '[max_dimensions][height]"]');
+ var $scheme = $(root + '[scheme]"]:checked');
var maxFileSize = $maxFileSize.val() ? $maxFileSize.val() : $maxFileSize.attr('placeholder');
var maxDimensions = ($maxWidth.val() && $maxHeight.val()) ? '(' + $maxWidth.val() + 'x' + $maxHeight.val() + ')' : '';
diff --git a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
index 5daf892..ecd6788 100644
--- a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
@@ -72,12 +72,6 @@ CKEDITOR.plugins.add('drupalimage', {
dialogClass: 'editor-image-dialog'
};
- // Add upload-image field based on the textarea's "data-image-uploads"
- // attribute.
- if (editor.element.$.attributes['data-editor-uploads']) {
- existingValues['uploadsEnabled'] = 1;
- }
-
// Open the dialog for the edit form.
Drupal.ckeditor.openDialog(editor, Drupal.url('editor/dialog/image/' + editor.config.drupal.format), existingValues, saveCallback, dialogSettings);
}
diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/DrupalImage.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/DrupalImage.php
index e3f73a7..db84e20 100644
--- a/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/DrupalImage.php
+++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Plugin/CKEditorPlugin/DrupalImage.php
@@ -64,105 +64,33 @@ public function getButtons() {
/**
* {@inheritdoc}
+ *
+ * @see \Drupal\editor\Form\EditorImageDialog
+ * @see editor_image_upload_settings_form()
*/
public function settingsForm(array $form, array &$form_state, Editor $editor) {
- // Defaults.
- $editor->settings['image_upload'] = isset($editor->settings['image_upload']) ? $editor->settings['image_upload'] : array();
- $editor->settings['image_upload'] += array(
- 'scheme' => file_default_scheme(),
- 'directory' => 'inline-images',
- 'max_size' => '',
- 'max_dimensions' => array('width' => '', 'height' => ''),
- );
-
- // Validate all settings as a group.
- $form['#element_validate'] = array(
- array($this, 'validateImageUploadValues'),
- );
- $form['#attached'] = array(
- 'library' => array(array('ckeditor', 'drupal.ckeditor.drupalimage.admin')),
- );
-
- $default_max_size = format_size(file_upload_max_size());
- $form['max_size'] = array(
- '#type' => 'textfield',
- '#default_value' => $editor->settings['image_upload']['max_size'],
- '#title' => t('Maximum file size'),
- '#description' => t('If this is left empty, then the file size will be limited by the PHP maximum upload size of @size', array('@size' => $default_max_size)),
- '#maxlength' => 20,
- '#size' => 10,
- '#placeholder' => $default_max_size,
- );
-
- $form['max_dimensions'] = array(
- '#type' => 'item',
- '#title' => t('Maximum dimensions'),
- '#field_prefix' => '
',
- '#field_suffix' => '
',
- '#description' => t('Images larger than these dimensions will be scaled down.'),
- );
- $form['max_dimensions']['width'] = array(
- '#title' => t('Width'),
- '#title_display' => 'invisible',
- '#type' => 'number',
- '#default_value' => $editor->settings['image_upload']['max_dimensions']['width'],
- '#size' => 8,
- '#maxlength' => 8,
- '#min' => 1,
- '#max' => 99999,
- '#placeholder' => 'width',
- '#field_suffix' => ' x ',
- );
- $form['max_dimensions']['height'] = array(
- '#title' => t('Height'),
- '#title_display' => 'invisible',
- '#type' => 'number',
- '#default_value' => $editor->settings['image_upload']['max_dimensions']['height'],
- '#size' => 8,
- '#maxlength' => 8,
- '#min' => 1,
- '#max' => 99999,
- '#placeholder' => 'height',
- '#field_suffix' => 'pixels',
- );
-
- // Any visible, writable wrapper can potentially be used for uploads,
- // including a remote file system that integrates with a CDN.
- $stream_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE);
- foreach ($stream_wrappers as $scheme => $info) {
- $options[$scheme] = $info['description'];
- }
-
- $config = config('system.file');
- if (!empty($options)) {
- $form['scheme'] = array(
- '#type' => 'radios',
- '#title' => t('File storage scheme'),
- '#default_value' => $editor->settings['image_upload']['scheme'],
- '#options' => $options,
- '#access' => count($options) > 1,
- );
- }
-
- foreach ($stream_wrappers as $scheme => $info) {
- $form['scheme'][$scheme]['#attributes']['data-label'] = t('Storage: @name', array('@name' => $info['name']));
- }
-
- $form['directory'] = array(
- '#type' => 'textfield',
- '#default_value' => $editor->settings['image_upload']['directory'],
- '#title' => t('Upload directory'),
- '#description' => t('A directory relative to Drupal\'s files directory where upload images will be stored.'),
+ form_load_include($form_state, 'inc', 'editor', 'editor.admin');
+ $form['image_upload'] = editor_image_upload_settings_form($editor);
+ $form['image_upload']['#attached']['library'][] = array('ckeditor', 'drupal.ckeditor.drupalimage.admin');
+ $form['image_upload']['#element_validate'] = array(
+ array($this, 'validateImageUploadSettings'),
);
return $form;
}
- function validateImageUploadValues(array $element, array &$form_state) {
- $settings = &$form_state['values']['editor']['settings']['plugins']['drupalimage'];
-
- // Save the settings at the editor level, not the plugin.
- $form_state['values']['editor']['settings']['image_upload'] = $settings;
+ /**
+ * #element_validate handler for the "image_upload" element in settingsForm().
+ *
+ * Moves the text editor's image upload settings from the DrupalImage plugin's
+ * own settings into $editor->image_upload.
+ *
+ * @see \Drupal\editor\Form\EditorImageDialog
+ * @see editor_image_upload_settings_form()
+ */
+ function validateImageUploadSettings(array $element, array &$form_state) {
+ $settings = &$form_state['values']['editor']['settings']['plugins']['drupalimage']['image_upload'];
+ $form_state['editor']->image_upload = $settings;
unset($form_state['values']['editor']['settings']['plugins']['drupalimage']);
}
diff --git a/core/modules/editor/config/schema/editor.schema.yml b/core/modules/editor/config/schema/editor.schema.yml
index 6654b88..4e2c985 100644
--- a/core/modules/editor/config/schema/editor.schema.yml
+++ b/core/modules/editor/config/schema/editor.schema.yml
@@ -12,6 +12,32 @@ editor.editor.*:
label: 'Text editor'
settings:
type: editor.settings.[%parent.editor]
+ image_upload:
+ type: mapping
+ label: 'Image upload settings'
+ mapping:
+ status:
+ type: boolean
+ label: 'Status'
+ scheme:
+ type: string
+ label: 'File storage'
+ directory:
+ type: string
+ label: 'Upload directory'
+ max_size:
+ type: string
+ label: 'Maximum file size'
+ max_dimensions:
+ type: mapping
+ label: 'Maximum dimensions'
+ mapping:
+ width:
+ type: integer
+ label: 'Maximum width'
+ height:
+ type: integer
+ label: 'Maximum height'
status:
type: boolean
label: 'Status'
diff --git a/core/modules/editor/editor.admin.inc b/core/modules/editor/editor.admin.inc
new file mode 100644
index 0000000..329f686
--- /dev/null
+++ b/core/modules/editor/editor.admin.inc
@@ -0,0 +1,131 @@
+image_upload = isset($editor->image_upload) ? $editor->image_upload : array();
+ $editor->image_upload += array(
+ 'status' => FALSE,
+ 'scheme' => file_default_scheme(),
+ 'directory' => 'inline-images',
+ 'max_size' => '',
+ 'max_dimensions' => array('width' => '', 'height' => ''),
+ );
+
+ $form['status'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Enable image uploads'),
+ '#default_value' => $editor->image_upload['status'],
+ '#attributes' => array(
+ 'data-editor-image-upload' => 'status',
+ ),
+ );
+ $show_if_image_uploads_enabled = array(
+ 'visible' => array(
+ ':input[data-editor-image-upload="status"]' => array('checked' => TRUE),
+ ),
+ );
+
+ // Any visible, writable wrapper can potentially be used for uploads,
+ // including a remote file system that integrates with a CDN.
+ $stream_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE);
+ foreach ($stream_wrappers as $scheme => $info) {
+ $options[$scheme] = $info['description'];
+ }
+ if (!empty($options)) {
+ $form['scheme'] = array(
+ '#type' => 'radios',
+ '#title' => t('File storage'),
+ '#default_value' => $editor->image_upload['scheme'],
+ '#options' => $options,
+ '#states' => $show_if_image_uploads_enabled,
+ '#access' => count($options) > 1,
+ );
+ }
+ // Set data- attributes with human-readable names for all possible stream
+ // wrappers, so that drupal.ckeditor.drupalimage.admin's summary rendering
+ // can use that.
+ foreach ($stream_wrappers as $scheme => $info) {
+ $form['scheme'][$scheme]['#attributes']['data-label'] = t('Storage: @name', array('@name' => $info['name']));
+ }
+
+ $form['directory'] = array(
+ '#type' => 'textfield',
+ '#default_value' => $editor->image_upload['directory'],
+ '#title' => t('Upload directory'),
+ '#description' => t('A directory relative to Drupal\'s files directory where uploaded images will be stored.'),
+ '#states' => $show_if_image_uploads_enabled,
+ );
+
+ $default_max_size = format_size(file_upload_max_size());
+ $form['max_size'] = array(
+ '#type' => 'textfield',
+ '#default_value' => $editor->image_upload['max_size'],
+ '#title' => t('Maximum file size'),
+ '#description' => t('If this is left empty, then the file size will be limited by the PHP maximum upload size of @size.', array('@size' => $default_max_size)),
+ '#maxlength' => 20,
+ '#size' => 10,
+ '#placeholder' => $default_max_size,
+ '#states' => $show_if_image_uploads_enabled,
+ );
+
+ $form['max_dimensions'] = array(
+ '#type' => 'item',
+ '#title' => t('Maximum dimensions'),
+ '#field_prefix' => '',
+ '#field_suffix' => '
',
+ '#description' => t('Images larger than these dimensions will be scaled down.'),
+ '#states' => $show_if_image_uploads_enabled,
+ );
+ $form['max_dimensions']['width'] = array(
+ '#title' => t('Width'),
+ '#title_display' => 'invisible',
+ '#type' => 'number',
+ '#default_value' => $editor->image_upload['max_dimensions']['width'],
+ '#size' => 8,
+ '#maxlength' => 8,
+ '#min' => 1,
+ '#max' => 99999,
+ '#placeholder' => 'width',
+ '#field_suffix' => ' x ',
+ '#states' => $show_if_image_uploads_enabled,
+ );
+ $form['max_dimensions']['height'] = array(
+ '#title' => t('Height'),
+ '#title_display' => 'invisible',
+ '#type' => 'number',
+ '#default_value' => $editor->image_upload['max_dimensions']['height'],
+ '#size' => 8,
+ '#maxlength' => 8,
+ '#min' => 1,
+ '#max' => 99999,
+ '#placeholder' => 'height',
+ '#field_suffix' => 'pixels',
+ '#states' => $show_if_image_uploads_enabled,
+ );
+
+ return $form;
+}
diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module
index eb97e0f..c8d5e33 100644
--- a/core/modules/editor/editor.module
+++ b/core/modules/editor/editor.module
@@ -8,7 +8,7 @@
use Drupal\file\Plugin\Core\Entity\File;
use Drupal\editor\Plugin\Core\Entity\Editor;
use Drupal\Component\Utility\NestedArray;
-use Drupal\system\SystemConfigFormBase;
+use Drupal\Core\Entity\EntityInterface;
/**
* Implements hook_help().
@@ -56,7 +56,6 @@ function editor_menu_alter(&$items) {
*/
function editor_element_info() {
$type['text_format'] = array(
- '#editor_uploads' => FALSE,
'#pre_render' => array('editor_pre_render_format'),
);
return $type;
@@ -377,11 +376,6 @@ function editor_pre_render_format($element) {
$element['format']['format']['#attributes']['data-editor-for'] = $field_id;
}
- // Set a data attribute if uploads are enabled.
- if ($element['#editor_uploads']) {
- $element['value']['#attributes']['data-editor-uploads'] = 'true';
- }
-
// Attach Text Editor module's (this module) library.
$element['#attached']['library'][] = array('editor', 'drupal.editor');
@@ -391,3 +385,183 @@ function editor_pre_render_format($element) {
return $element;
}
+
+/**
+ * Implements hook_entity_insert().
+ */
+function editor_entity_insert(EntityInterface $entity) {
+ $referenced_files_by_field = _editor_get_file_uuids_by_field($entity);
+ foreach ($referenced_files_by_field as $field => $uuids) {
+ _editor_record_file_usage($uuids, $entity);
+ }
+}
+
+/**
+ * Implements hook_entity_update().
+ */
+function editor_entity_update(EntityInterface $entity) {
+ // On new revisions, all files are considered to be a new usage and no
+ // deletion of previous file usages are necessary.
+ if (!empty($entity->original) && $entity->getRevisionId() != $entity->original->getRevisionId()) {
+ $referenced_files = _editor_get_file_uuids_by_field($entity);
+ _editor_record_file_usage($referenced_files, $entity);
+ }
+ // On modified revisions, detect which file references have been added (and
+ // record their usage) and which ones have been removed (delete their usage).
+ // File references that existed both in the previous version of the revision
+ // and in the new one don't need their usage to be updated.
+ else {
+ $original_uuids_by_field = _editor_get_file_uuids_by_field($entity->original);
+ $uuids_by_field = _editor_get_file_uuids_by_field($entity);
+
+ // Detect file usages that should be incremented.
+ foreach ($uuids_by_field as $field => $uuids) {
+ $added_files = array_diff($uuids_by_field[$field], $original_uuids_by_field);
+ _editor_record_file_usage($added_files, $entity);
+ }
+
+ // Detect file usages that should be decremented.
+ foreach ($original_uuids_by_field as $field => $uuids) {
+ $removed_files = array_diff($original_uuids_by_field[$field], $uuids_by_field);
+ _editor_delete_file_usage($removed_files, $entity, 1);
+ }
+ }
+}
+
+/**
+ * Implements hook_entity_delete().
+ */
+function editor_entity_delete(EntityInterface $entity) {
+ $referenced_files_by_field = _editor_get_file_uuids_by_field($entity);
+ foreach ($referenced_files_by_field as $field => $uuids) {
+ _editor_delete_file_usage($uuids, $entity, 0);
+ }
+}
+
+/**
+ * Implements hook_entity_revision_delete().
+ */
+function editor_entity_revision_delete(EntityInterface $entity) {
+ $referenced_files_by_field = _editor_get_file_uuids_by_field($entity);
+ foreach ($referenced_files_by_field as $field => $uuids) {
+ _editor_delete_file_usage($uuids, $entity, 1);
+ }
+}
+
+/**
+ * Records file usage of files referenced by processed text fields.
+ *
+ * Every referenced file that does not yet have the FILE_STATUS_PERMANENT state,
+ * will be given that state.
+ *
+ * @param array $uuids
+ * An array of file entity UUIDs.
+ * @param EntityInterface $entity
+ * An entity whose fields to inspect for file references.
+ */
+function _editor_record_file_usage(array $uuids, EntityInterface $entity) {
+ foreach ($uuids as $uuid) {
+ $file = entity_load_by_uuid('file', $uuid);
+ if ($file->status !== FILE_STATUS_PERMANENT) {
+ $file->status = FILE_STATUS_PERMANENT;
+ $file->save();
+ }
+ file_usage()->add($file, 'editor', $entity->entityType(), $entity->id());
+ }
+}
+
+/**
+ * Deletes file usage of files referenced by processed text fields.
+ *
+ * @param array $uuids
+ * An array of file entity UUIDs.
+ * @param EntityInterface $entity
+ * An entity whose fields to inspect for file references.
+ * @param $count
+ * The number of references to delete. Should be 1 when deleting a single
+ * revision and 0 when deleting an entity entirely.
+ *
+ * @see Drupal\file\FileUsage\FileUsageInterface::delete()
+ */
+function _editor_delete_file_usage(array $uuids, EntityInterface $entity, $count) {
+ foreach ($uuids as $uuid) {
+ $file = entity_load_by_uuid('file', $uuid);
+ file_usage()->delete($file, 'editor', $entity->entityType(), $entity->id(), $count);
+ }
+}
+
+/**
+ * Finds all files referenced (data-editor-file-uuid) by processed text fields.
+ *
+ * @param EntityInterface $entity
+ * An entity whose fields to analyze.
+ *
+ * @return array
+ * An array of file entity UUIDs.
+ */
+function _editor_get_file_uuids_by_field(EntityInterface $entity) {
+ $uuids = array();
+
+ $processed_text_fields = _editor_get_processed_text_fields($entity);
+ foreach ($processed_text_fields as $processed_text_field) {
+ $text = $entity->get($processed_text_field)->value;
+ $uuids[$processed_text_field] = _editor_parse_file_uuids($text);
+ }
+ return $uuids;
+}
+
+/**
+ * Determines the text fields on an entity that have text processing enabled.
+ *
+ * @param EntityInterface $entity
+ * An entity whose fields to analyze.
+ *
+ * @return array
+ * The names of the fields on this entity that have text processing enabled.
+ */
+function _editor_get_processed_text_fields(EntityInterface $entity) {
+ $text_field_types = array(
+ 'field_item:text',
+ 'field_item:text_long',
+ 'field_item:text_with_summary'
+ );
+
+ $properties = $entity->getPropertyDefinitions();
+ if (empty($properties)) {
+ return array();
+ }
+
+ // Find all fields of one of the text field types.
+ $fields = array_keys(array_filter($properties, function ($definition) use ($text_field_types) {
+ return in_array($definition['type'], $text_field_types);
+ }));
+ if (empty($fields)) {
+ return array();
+ }
+
+ // Only return fields that have text processing enabled.
+ return array_filter($fields, function ($field) use ($entity) {
+ $instance = field_info_instance($entity->entityType(), $field, $entity->bundle());
+ return $instance->getFieldSetting('text_processing') === '1';
+ });
+}
+
+/**
+ * Parse an HTML snippet for any data-editor-file-uuid attributes.
+ *
+ * @param string $text
+ * The partial (X)HTML snippet to load. Invalid markup will be corrected on
+ * import.
+ *
+ * @return array
+ * An array of all found UUIDs.
+ */
+function _editor_parse_file_uuids($text) {
+ $dom = filter_dom_load($text);
+ $xpath = new \DOMXPath($dom);
+ $uuids = array();
+ foreach ($xpath->query('//*[@data-editor-file-uuid]') as $node) {
+ $uuids[] = $node->getAttribute('data-editor-file-uuid');
+ }
+ return $uuids;
+}
diff --git a/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php b/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php
index 8d44118..7398207 100644
--- a/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php
+++ b/core/modules/editor/lib/Drupal/editor/Form/EditorImageDialog.php
@@ -47,21 +47,21 @@ public function buildForm(array $form, array &$form_state, FilterFormat $filter_
$editor = editor_load($filter_format->format);
// Construct strings to use in the upload validators.
- if (!empty($editor->settings['image_upload']['dimensions'])) {
- $max_dimensions = $editor->settings['image_upload']['dimensions']['max_width'] . 'x' . $editor->settings['image_upload']['dimensions']['max_height'];
+ if (!empty($editor->image_upload['dimensions'])) {
+ $max_dimensions = $editor->image_upload['dimensions']['max_width'] . 'x' . $editor->image_upload['dimensions']['max_height'];
}
else {
$max_dimensions = 0;
}
- $max_filesize = min(parse_size($editor->settings['image_upload']['max_size']), file_upload_max_size());
+ $max_filesize = min(parse_size($editor->image_upload['max_size']), file_upload_max_size());
- $existing_file = isset($input['data-file-uuid']) ? entity_load_by_uuid('file', $input['data-file-uuid']) : NULL;
+ $existing_file = isset($input['data-editor-file-uuid']) ? entity_load_by_uuid('file', $input['data-editor-file-uuid']) : NULL;
$fid = $existing_file ? $existing_file->id() : NULL;
$form['fid'] = array(
'#title' => t('Image'),
'#type' => 'managed_file',
- '#upload_location' => $editor->settings['image_upload']['scheme'] . '://' .$editor->settings['image_upload']['directory'],
+ '#upload_location' => $editor->image_upload['scheme'] . '://' .$editor->image_upload['directory'],
'#default_value' => $fid ? array($fid) : NULL,
'#upload_validators' => array(
'file_validate_extensions' => array('gif png jpg jpeg'),
@@ -79,14 +79,10 @@ public function buildForm(array $form, array &$form_state, FilterFormat $filter_
'#required' => TRUE,
);
- // If the editor has uploads enabled and the field was requested, show
- // an upload field. Otherwise only a plain "src" field is shown.
- $uploads_enabled = !empty($form_state['uploads_enabled']) || !empty($input['uploadsEnabled']);
- if ($uploads_enabled && !empty($editor->settings['image_upload'])) {
+ // If the editor has image uploads enabled, show a managed_file form item,
+ // otherwise show a (file URL) text form item.
+ if ($editor->image_upload['status'] === '1') {
$form['attributes']['src']['#access'] = FALSE;
- // Set a flag in form state so the upload field stays accessible during
- // the validation and submit handling.
- $form_state['uploads_enabled'] = TRUE;
}
else {
$form['fid']['#access'] = FALSE;
@@ -160,13 +156,14 @@ public function validateForm(array &$form, array &$form_state) {
public function submitForm(array &$form, array &$form_state) {
$response = new AjaxResponse();
- // Convert any uploaded files from the FID values to data-uuid attributes.
+ // Convert any uploaded files from the FID values to data-editor-file-uuid
+ // attributes.
if (!empty($form_state['values']['fid'][0])) {
$file = file_load($form_state['values']['fid'][0]);
$uri = $file->getFileUri();
$stream = file_stream_wrapper_get_instance_by_uri($uri);
$form_state['values']['attributes']['src'] = str_replace($_SERVER['DOCUMENT_ROOT'], '', $stream->realpath());
- $form_state['values']['attributes']['data-file-uuid'] = $file->uuid();
+ $form_state['values']['attributes']['data-editor-file-uuid'] = $file->uuid();
}
if (form_get_errors()) {
diff --git a/core/modules/editor/lib/Drupal/editor/Plugin/Core/Entity/Editor.php b/core/modules/editor/lib/Drupal/editor/Plugin/Core/Entity/Editor.php
index 710b991..48e4a77 100644
--- a/core/modules/editor/lib/Drupal/editor/Plugin/Core/Entity/Editor.php
+++ b/core/modules/editor/lib/Drupal/editor/Plugin/Core/Entity/Editor.php
@@ -47,13 +47,20 @@ class Editor extends ConfigEntityBase implements EditorInterface {
public $editor;
/**
- * The array of settings for the text editor.
+ * The array of text editor plugin-specific settings for the text editor.
*
* @var array
*/
public $settings = array();
/**
+ * The array of image upload settings for the text editor.
+ *
+ * @var array
+ */
+ public $image_upload = array();
+
+ /**
* Overrides Drupal\Core\Entity\Entity::id().
*/
public function id() {
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
index 6dd9330..298ce8d 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
@@ -81,9 +81,6 @@ public function formElement(FieldInterface $items, $delta, array $element, $lang
$element['#type'] = 'text_format';
$element['#format'] = $items[$delta]->format;
$element['#base_type'] = $main_widget['#type'];
- if (module_exists('editor')) {
- $element['#editor_uploads'] = TRUE;
- }
}
else {
$element['value'] = $main_widget;
diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php
index 82a4c2d..352420d 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -82,50 +82,11 @@ public function getValue($langcode = NULL) {
* Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
*/
public function setValue($value, $notify = TRUE) {
-
- // @todo: We don't have enough context here to adequately determine if files
- // have been removed from an current revision. Likewise we don't have the
- // ability to decrement a usage when a revision is deleted. Switch to using
- // hooks for hook_entity_insert/update/delete/revision_delete()?
- if (isset($value) && module_exists('editor')) {
- // Parse the value for any file usages and increment/decrement them as
- // needed.
- $field = $this->parent->getParent();
- $entity = $field->getParent();
- $instance = field_info_instance($entity->entityType(), $field->getName(), $entity->bundle());
-
- $uuids = parseFileUuids($value);
- $xpath = new \DOMXPath($dom);
- foreach ($xpath->query('//*[@data-file-uuid]') as $node) {
- $file_uuid = $node->getAttribute('data-file-uuid');
- $file = entity_load_by_uuid('file', $file_uuid);
- if ($file->status !== FILE_STATUS_PERMANENT) {
- $file->status = FILE_STATUS_PERMANENT;
- $file->save();
- }
- file_usage()->add($file, 'file', $entity->entityType(), $entity->id());
- }
-
+ if (isset($value)) {
// @todo This is triggered from DatabaseStorageController::invokeFieldMethod()
// in the case of case of non-NG entity types.
// throw new ReadOnlyException('Unable to set a computed property.');
}
}
- /**
- * Parse text for any data-file-uuid attributes.
- *
- * @param string $value
- * The string of data being saved in this field.
- * @return array
- * An array of all found UUIDs.
- */
- protected function parseFileUuids($value) {
- $dom = filter_dom_load($value);
- $xpath = new \DOMXPath($dom);
- $uuids = array();
- foreach ($xpath->query('//*[@data-file-uuid]') as $node) {
- $uuids[] = $node->getAttribute('data-file-uuid');
- }
- }
}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php
index 645e10d..71124a2 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/Text.php
@@ -39,7 +39,7 @@ public function buildOptionsForm(&$form, &$form_state) {
'#default_value' => $this->options['content'],
'#rows' => 6,
'#format' => isset($this->options['format']) ? $this->options['format'] : filter_default_format(),
- '#wysiwyg' => FALSE,
+ '#editor' => FALSE,
);
}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php b/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php
index 5a94674..ec35078 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/exposed_form/InputRequired.php
@@ -41,7 +41,7 @@ public function buildOptionsForm(&$form, &$form_state) {
'#description' => t('Text to display instead of results until the user selects and applies an exposed filter.'),
'#default_value' => $this->options['text_input_required'],
'#format' => isset($this->options['text_input_required_format']) ? $this->options['text_input_required_format'] : filter_default_format(),
- '#wysiwyg' => FALSE,
+ '#editor' => FALSE,
);
}
diff --git a/core/profiles/standard/config/editor.editor.basic_html.yml b/core/profiles/standard/config/editor.editor.basic_html.yml
index cf4a600..e340685 100644
--- a/core/profiles/standard/config/editor.editor.basic_html.yml
+++ b/core/profiles/standard/config/editor.editor.basic_html.yml
@@ -20,5 +20,13 @@ settings:
plugins:
stylescombo:
styles: ''
+image_upload:
+ status: '1'
+ scheme: public
+ directory: inline-images
+ max_size: ''
+ max_dimensions:
+ width: ''
+ height: ''
status: '1'
langcode: und
diff --git a/core/profiles/standard/config/editor.editor.full_html.yml b/core/profiles/standard/config/editor.editor.full_html.yml
index c0111f9..eb01c1c 100644
--- a/core/profiles/standard/config/editor.editor.full_html.yml
+++ b/core/profiles/standard/config/editor.editor.full_html.yml
@@ -30,5 +30,13 @@ settings:
plugins:
stylescombo:
styles: ''
+image_upload:
+ status: '1'
+ scheme: public
+ directory: inline-images
+ max_size: ''
+ max_dimensions:
+ width: ''
+ height: ''
status: '1'
langcode: und