Commit 7f322d95 authored by Devin Carlson's avatar Devin Carlson

Issue #2142571 by Devin Carlson: Moved WYSIWYG functionality into a submodule.

parent 4a883196
......@@ -131,21 +131,6 @@
position: relative;
}
/* Format form */
#media-format-form {
margin: 20px;
}
#media-format-form .media-item {
float: left;
margin-right: 10px;
}
#media-format-form .form-item-format label {
display: inline;
}
/* File field */
.media-widget .preview {
......@@ -174,12 +159,6 @@
cursor: pointer;
}
/* Plupload */
body.page-media-format-form #media-browser-page .plupload_start {
display: none;
}
/* Multiedit */
.media-multiedit-form .media-edit-form {
......
......@@ -181,47 +181,6 @@ function media_admin_config_browser($form, &$form_state) {
'#default_value' => variable_get('media__dialog_theme', ''),
);
// Additional configuration if the WYSIWYG module is enabled.
$form['wysiwyg'] = array(
'#type' => 'fieldset',
'#title' => t('WYSIWYG configuration'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#access' => module_exists('wysiwyg'),
);
$plugins = media_get_browser_plugin_info();
$form['wysiwyg']['media__wysiwyg_browser_plugins'] = array(
'#type' => 'checkboxes',
'#title' => t('Enabled browser plugins'),
'#options' => array(),
'#required' => FALSE,
'#default_value' => variable_get('media__wysiwyg_browser_plugins', array()),
'#description' => t('If no plugins are selected, they will all be available.'),
);
foreach ($plugins as $key => $plugin) {
$form['wysiwyg']['media__wysiwyg_browser_plugins']['#options'][$key] = !empty($plugin['title']) ? $plugin['title'] : $key;
}
$form['wysiwyg']['media__wysiwyg_upload_directory'] = array(
'#type' => 'textfield',
'#title' => t("File directory for uploaded media"),
'#default_value' => variable_get('media__wysiwyg_upload_directory', ''),
'#description' => t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
);
if (module_exists('token')) {
$form['wysiwyg']['media__wysiwyg_upload_directory']['#description'] .= t('This field supports tokens.');
$form['wysiwyg']['tokens'] = array(
'#theme' => 'token_tree',
'#dialog' => TRUE,
);
}
$form['wysiwyg']['media__wysiwyg_allowed_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Allowed types in WYSIWYG'),
'#options' => file_entity_type_get_names(),
'#default_value' => variable_get('media__wysiwyg_allowed_types', array('audio', 'image', 'video', 'document')),
);
$form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
$form['#submit'][] = 'media_admin_config_browser_pre_submit';
......@@ -236,9 +195,4 @@ function media_admin_config_browser_pre_submit(&$form, &$form_state) {
variable_del('media__dialog_theme');
unset($form_state['values']['media__dialog_theme']);
}
$wysiwyg_browser_plugins = array_unique(array_values($form_state['values']['media__wysiwyg_browser_plugins']));
if (empty($wysiwyg_browser_plugins[0])) {
variable_del('media__wysiwyg_browser_plugins');
unset($form_state['values']['media__wysiwyg_browser_plugins']);
}
}
......@@ -102,68 +102,3 @@ function hook_media_browser_params_alter(&$stored_params) {
$stored_params['types'][] = 'document';
unset($stored_params['enabledPlugins'][0]);
}
/**
* Alter a list of view modes allowed for a file embedded in the WYSIWYG.
*
* @param array $view_modes
* An array of view modes that can be used on the file when embedded in the
* WYSIWYG.
* @param object $file
* A file entity.
*
* @see media_get_wysiwyg_allowed_view_modes()
*/
function hook_media_wysiwyg_allowed_view_modes_alter(&$view_modes, $file) {
$view_modes['default']['label'] = t('Display an unmodified version of the file');
unset($view_modes['preview']);
}
/**
* Alter the WYSIWYG view mode selection form.
*
* Similar to a form_alter, but runs first so that modules can add
* fields specific to a given file type (like alt tags on images) before alters
* begin to work on the fields.
*
* @param array $form
* An associative array containing the structure of the form.
* @param array $form_state
* An associative array containing the current state of the form.
* @param object $file
* A file entity.
*
* @see media_format_form()
*/
function hook_media_format_form_prepare_alter(&$form, &$form_state, $file) {
$form['preview']['#access'] = FALSE;
$file = $form['#media'];
$form['heading']['#markup'] = t('Embedding %filename of type %filetype', array('%filename' => $file->filename, '%filetype' => $file->type));
}
/**
* Alter the output generated by Media filter tags.
*
* @param array $element
* The renderable array of output generated for the filter tag.
* @param array $tag_info
* The filter tag converted into an associative array by
* media_token_to_markup() with the following elements:
* - 'fid': The ID of the media file being rendered.
* - 'file': The object from file_load() of the media file being rendered.
* - 'view_mode': The view mode being used to render the file.
* - 'attributes': An additional array of attributes that could be output
* with media_get_file_without_label().
* @param array $settings
* An additional array of settings.
* - 'wysiwyg': A boolean if the output is for the WYSIWYG preview or FALSE
* if for normal rendering.
*
* @see media_token_to_markup()
*/
function hook_media_token_to_markup_alter(&$element, $tag_info, $settings) {
if (empty($settings['wysiwyg'])) {
$element['#attributes']['alt'] = t('This media has been output using the @mode view mode.', array('@mode' => $tag_info['view_mode']));
}
}
......@@ -17,9 +17,6 @@ files[] = includes/MediaBrowserView.inc
files[] = includes/MediaEntityTranslationHandler.inc
files[] = includes/media_views_plugin_display_media_browser.inc
files[] = includes/media_views_plugin_style_media_browser.inc
files[] = tests/media.test
files[] = tests/media.entity.test
files[] = tests/media.file.usage.test
files[] = tests/media.macro.test
files[] = media.test
configure = admin/config/media/browser
......@@ -1071,3 +1071,12 @@ function media_update_7218() {
variable_del('media__xml_cache_expire');
}
/**
* Enable the Media WYSIWYG submodule.
*/
function media_update_7219() {
if (module_exists('wysiwyg')) {
module_enable(array('media_wysiwyg'));
}
}
......@@ -15,9 +15,6 @@
// Code relating to using media as a field.
require_once dirname(__FILE__) . '/includes/media.fields.inc';
// Functions for working with [[inline tags]] and wysiwyg editors.
require_once dirname(__FILE__) . '/includes/media.filter.inc';
/* ***************************************** */
/* Hook Implementations */
/* ***************************************** */
......@@ -32,9 +29,6 @@ function media_hook_info() {
'media_browser_plugin_info_alter',
'media_browser_plugins_alter',
'media_browser_params_alter',
'media_wysiwyg_allowed_view_modes_alter',
'media_format_form_prepare_alter',
'media_token_to_markup_alter',
'query_media_browser_alter',
);
......@@ -162,18 +156,6 @@ function media_menu() {
'file' => 'includes/media.browser.inc',
);
$items['media/%file/format-form'] = array(
'title' => 'Style selector',
'description' => 'Choose a format for a piece of media',
'page callback' => 'drupal_get_form',
'page arguments' => array('media_format_form', 1),
'access callback' => 'file_entity_access',
'access arguments' => array('view', 1),
'file' => 'includes/media.filter.inc',
'theme callback' => 'media_dialog_get_theme_name',
'type' => MENU_CALLBACK,
);
if (module_exists('multiform')) {
// @todo Investigate passing file IDs in query string rather than a menu
// argument and then deprecate media_multi_load().
......@@ -356,13 +338,6 @@ function media_page_alter(&$page) {
}
}
/**
* Implements hook_element_info_alter().
*/
function media_element_info_alter(&$types) {
$types['text_format']['#pre_render'][] = 'media_pre_render_text_format';
}
/**
* Implements hook_file_operations().
*/
......@@ -547,16 +522,6 @@ function media_browser_form_submit($form, &$form_state) {
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function media_form_wysiwyg_profile_form_alter(&$form, &$form_state) {
// Add warnings if the media filter is disabled for the WYSIWYG's text format.
$form['buttons']['drupal']['media']['#element_validate'][] = 'media_wysiwyg_button_element_validate';
$form['buttons']['drupal']['media']['#after_build'][] = 'media_wysiwyg_button_element_validate';
form_load_include($form_state, 'inc', 'media', 'wysiwyg_plugins/media');
}
/**
* Access callback for the media-multi form.
*
......@@ -957,27 +922,6 @@ function media_element_validate(&$element, &$form_state) {
}
}
/**
* Implements hook_filter_info().
*/
function media_filter_info() {
$filters['media_filter'] = array(
'title' => t('Convert Media tags to markup'),
'description' => t('This filter will convert [[{type:media... ]] tags into markup.'),
'process callback' => 'media_filter',
'weight' => 2,
// @TODO not implemented
'tips callback' => 'media_filter_tips',
);
// If the WYSIWYG module is enabled, add additional help.
if (module_exists('wysiwyg')) {
$filters['media_filter']['description'] .= ' ' . t('This must be enabled for the Media WYSIWYG integration to work with this input format.');
}
return $filters;
}
/**
* Media thumbnail render function.
*
......@@ -1299,28 +1243,3 @@ function _media_get_migratable_file_types() {
return array_diff($types, $enabled_types);
}
/**
* Returns the default set of allowed attributes for use with WYSIWYG.
*
* @return array
* An array of whitelisted attributes.
*/
function _media_wysiwyg_allowed_attributes_default() {
return array(
'alt',
'title',
'height',
'width',
'hspace',
'vspace',
'border',
'align',
'style',
'class',
'id',
'usemap',
'data-picture-group',
'data-picture-align',
);
}
<?php
/**
* @file
* Tests for media.module.
*/
/**
* Defines base class for media test cases.
*/
class MediaTestHelper extends DrupalWebTestCase {
/**
* Enable media and file entity modules for testing.
*/
public function setUp() {
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
$modules = $modules[0];
}
$modules[] = 'media';
parent::setUp($modules);
}
}
/**
* @file
* Styles for the format form.
*
* The display and layout of the Media browser assumes Drupal's Seven theme as
* the theme active when this is displayed.
*/
#media-wysiwyg-format-form {
margin: 20px;
}
#media-wysiwyg-format-form .media-item {
float: left;
margin-right: 10px;
}
#media-wysiwyg-format-form .form-item-format label {
display: inline;
}
/* Plupload */
body.page-media-wysiwyg-format-form #media-browser-page .plupload_start {
display: none;
}
<?php
/**
* @file
* Functions related to the tracking the file usage of embedded media.
*/
/**
* Implements hook_field_attach_insert().
*
* Track file usage for media files included in formatted text. Note that this
* is heavy-handed, and should be replaced when Drupal's filter system is
* context-aware.
*/
function media_wysiwyg_field_attach_insert($entity_type, $entity) {
_media_wysiwyg_filter_add_file_usage_from_fields($entity_type, $entity);
}
/**
* Implements hook_field_attach_update().
*
* @see media_field_attach_insert().
*/
function media_wysiwyg_field_attach_update($entity_type, $entity) {
_media_wysiwyg_filter_add_file_usage_from_fields($entity_type, $entity);
}
/**
* Add file usage from file references in an entity's text fields.
*/
function _media_wysiwyg_filter_add_file_usage_from_fields($entity_type, $entity) {
// Track the total usage for files from all fields combined.
$entity_files = media_wysiwyg_entity_field_count_files($entity_type, $entity);
list($entity_id, $entity_vid, $entity_bundle) = entity_extract_ids($entity_type, $entity);
// When an entity has revisions and then is saved again NOT as new version the
// previous revision of the entity has be loaded to get the last known good
// count of files. The saved data is compared against the last version
// so that a correct file count can be created for that (the current) version
// id. This code may assume some things about entities that are only true for
// node objects. This should be reviewed.
// @TODO this conditional can probably be condensed
if (empty($entity->revision) && empty($entity->old_vid) && empty($entity->is_new) && ! empty($entity->original)) {
$old_files = media_wysiwyg_entity_field_count_files($entity_type, $entity->original);
foreach ($old_files as $fid => $old_file_count) {
// Were there more files on the node just prior to saving?
if (empty($entity_files[$fid])) {
$entity_files[$fid] = 0;
}
if ($old_file_count > $entity_files[$fid]) {
$deprecate = $old_file_count - $entity_files[$fid];
// Now deprecate this usage
$file = file_load($fid);
if ($file) {
file_usage_delete($file, 'media', $entity_type, $entity_id, $deprecate);
}
// Usage is deleted, nothing more to do with this file
unset($entity_files[$fid]);
}
// There are the same number of files, nothing to do
elseif ($entity_files[$fid] == $old_file_count) {
unset($entity_files[$fid]);
}
// There are more files now, adjust the difference for the greater number.
// file_usage incrementing will happen below.
else {
// We just need to adjust what the file count will account for the new
// images that have been added since the increment process below will
// just add these additional ones in
$entity_files[$fid] = $entity_files[$fid] - $old_file_count;
}
}
}
// Each entity revision counts for file usage. If versions are not enabled
// the file_usage table will have no entries for this because of the delete
// query above.
foreach ($entity_files as $fid => $entity_count) {
if ($file = file_load($fid)) {
file_usage_add($file, 'media', $entity_type, $entity_id, $entity_count);
}
}
}
/**
* Parse file references from an entity's text fields and return them as an array.
*/
function media_wysiwyg_filter_parse_from_fields($entity_type, $entity) {
$file_references = array();
foreach (media_wysiwyg_filter_fields_with_text_filtering($entity_type, $entity) as $field_name) {
if ($field_items = field_get_items($entity_type, $entity, $field_name)) {
foreach ($field_items as $field_item) {
preg_match_all(MEDIA_WYSIWYG_TOKEN_REGEX, $field_item['value'], $matches);
foreach ($matches[0] as $tag) {
$tag = str_replace(array('[[', ']]'), '', $tag);
$tag_info = drupal_json_decode($tag);
if (isset($tag_info['fid']) && $tag_info['type'] == 'media') {
$file_references[] = $tag_info;
}
}
preg_match_all(MEDIA_WYSIWYG_TOKEN_REGEX, $field_item['value'], $matches_alt);
foreach ($matches_alt[0] as $tag) {
$tag = urldecode($tag);
$tag_info = drupal_json_decode($tag);
if (isset($tag_info['fid']) && $tag_info['type'] == 'media') {
$file_references[] = $tag_info;
}
}
}
}
}
return $file_references;
}
/**
* Utility function to get the file count in this entity
*
* @param type $entity
* @param type $entity_type
* @return int
*/
function media_wysiwyg_entity_field_count_files($entity_type, $entity) {
$entity_files = array();
foreach (media_wysiwyg_filter_parse_from_fields($entity_type, $entity) as $file_reference) {
if (empty($entity_files[$file_reference['fid']])) {
$entity_files[$file_reference['fid']] = 1;
}
else {
$entity_files[$file_reference['fid']]++;
}
}
return $entity_files;
}
/**
* Implements hook_entity_delete().
*/
function media_wysiwyg_entity_delete($entity, $type) {
list($entity_id) = entity_extract_ids($type, $entity);
db_delete('file_usage')
->condition('module', 'media')
->condition('type', $type)
->condition('id', $entity_id)
->execute();
}
/**
* Implements hook_field_attach_delete_revision().
*
* @param type $entity_type
* @param type $entity
*/
function media_wysiwyg_field_attach_delete_revision($entity_type, $entity) {
list($entity_id) = entity_extract_ids($entity_type, $entity);
$files = media_wysiwyg_entity_field_count_files($entity_type, $entity);
foreach ($files as $fid => $count) {
if ($file = file_load($fid)) {
file_usage_delete($file, 'media', $entity_type , $entity_id, $count);
}
}
}
/**
* Implements hook_entity_dependencies().
*/
function media_wysiwyg_entity_dependencies($entity, $entity_type) {
// Go through all the entity's text fields and add a dependency on any files
// that are referenced there.
$dependencies = array();
foreach (media_wysiwyg_filter_parse_from_fields($entity_type, $entity) as $file_reference) {
$dependencies[] = array('type' => 'file', 'id' => $file_reference['fid']);
}
return $dependencies;
}
<?php
/**
* @file
* Functions related to adding UUID support to embedded media.
*/
/**
* Implements hook_entity_uuid_load().
*/
function media_wysiwyg_entity_uuid_load(&$entities, $entity_type) {
// Go through all the entity's text fields and replace file IDs in media
// tokens with the corresponding UUID.
foreach ($entities as $entity) {
media_wysiwyg_filter_replace_tokens_in_all_text_fields($entity_type, $entity, 'media_token_fid_to_uuid');
}
}
/**
* Implements hook_entity_uuid_presave().
*/
function media_wysiwyg_entity_uuid_presave(&$entity, $entity_type) {
// Go through all the entity's text fields and replace UUIDs in media tokens
// with the corresponding file ID.
media_wysiwyg_filter_replace_tokens_in_all_text_fields($entity_type, $entity, 'media_token_uuid_to_fid');
}
/**
* Replaces media tokens in an entity's text fields, using the specified callback function.
*/
function media_wysiwyg_filter_replace_tokens_in_all_text_fields($entity_type, $entity, $callback) {
$text_field_names = media_wysiwyg_filter_fields_with_text_filtering($entity_type, $entity);
foreach ($text_field_names as $field_name) {
if (!empty($entity->{$field_name})) {
$field = field_info_field($field_name);
$all_languages = field_available_languages($entity_type, $field);
$field_languages = array_intersect($all_languages, array_keys($entity->{$field_name}));
foreach ($field_languages as $language) {
if (!empty($entity->{$field_name}[$language])) {
foreach ($entity->{$field_name}[$language] as &$item) {
$item['value'] = preg_replace_callback(MEDIA_WYSIWYG_TOKEN_REGEX, $callback, $item['value']);
}
}
}
}
}
}
/**
* Callback to replace file IDs with UUIDs in a media token.
*/
function media_wysiwyg_token_fid_to_uuid($matches) {
return _media_wysiwyg_token_uuid_replace($matches, 'entity_get_uuid_by_id');
}
/**
* Callback to replace UUIDs with file IDs in a media token.
*/
function media_wysiwyg_token_uuid_to_fid($matches) {
return _media_wysiwyg_token_uuid_replace($matches, 'entity_get_id_by_uuid');
}
/**
* Helper function to replace UUIDs with file IDs or vice versa.
*
* @param array $matches
* An array of matches for media tokens, from a preg_replace_callback()
* callback function.
* @param string $entity_uuid_function
* Either 'entity_get_uuid_by_id' (to replace file IDs with UUIDs in the
* token) or 'entity_get_id_by_uuid' (to replace UUIDs with file IDs).
*
* @return string
* A string representing the JSON-encoded token, with the appropriate
* replacement between file IDs and UUIDs.
*/
function _media_wysiwyg_token_uuid_replace($matches, $entity_uuid_function) {
$tag = $matches[0];
$tag = str_replace(array('[[', ']]'), '', $tag);
$tag_info = drupal_json_decode($tag);
if (isset($tag_info['fid'])) {
if ($new_ids = $entity_uuid_function('file', array($tag_info['fid']))) {
$new_id = reset($new_ids);
$tag_info['fid'] = $new_id;
}
}
return '[[' . drupal_json_encode($tag_info) . ']]';
}
......@@ -26,16 +26,16 @@ Drupal.behaviors.mediaFormatForm = {
// Adding the buttons should only be done once in order to prevent multiple
// buttons from being added if part of the form is updated via AJAX
$('#media-format-form').once('format', function() {
$('<a class="button fake-ok">' + Drupal.t('Submit') + '</a>').appendTo($('#media-format-form')).bind('click', Drupal.media.formatForm.submit);
$('<a class="button fake-cancel">' + Drupal.t('Cancel') + '</a>').appendTo($('#media-format-form')).bind('click', Drupal.media.formatForm.submit);
$('#media-wysiwyg-format-form').once('format', function() {
$('<a class="button fake-ok">' + Drupal.t('Submit') + '</a>').appendTo($('#media-wysiwyg-format-form')).bind('click', Drupal.media.formatForm.submit);
$('<a class="button fake-cancel">' + Drupal.t('Cancel') + '</a>').appendTo($('#media-wysiwyg-format-form')).bind('click', Drupal.media.formatForm.submit);
});
}
};
Drupal.media.formatForm.getOptions = function () {
// Get all the values
var ret = {}; $.each($('#media-format-form fieldset#edit-options *').serializeArray(), function (i, field) { ret[field.name] = field.value; });
var ret = {}; $.each($('#media-wysiwyg-format-form fieldset#edit-options *').serializeArray(), function (i, field) { ret[field.name] = field.value; });
return ret;
};
......
<?php
/**
* @file
* Hooks provided by the Media WYSIWYG module.
*/
/**
* Alter a list of view modes allowed for a file embedded in the WYSIWYG.
*
* @param array $view_modes
* An array of view modes that can be used on the file when embedded in the
* WYSIWYG.
* @param object $file
* A file entity.
*
* @see media_get_wysiwyg_allowed_view_modes()
*/
function hook_media_wysiwyg_wysiwyg_allowed_view_modes_alter(&$view_modes, $file) {
$view_modes['default']['label'] = t('Display an unmodified version of the file');
unset($view_modes['preview']);
}
/**
* Alter the WYSIWYG view mode selection form.
*
* Similar to a form_alter, but runs first so that modules can add
* fields specific to a given file type (like alt tags on images) before alters
* begin to work on the fields.
*
* @param array $form
* An associative array containing the structure of the form.
* @param array $form_state
* An associative array containing the current state of the form.
* @param object $file
* A file entity.
*
* @see media_format_form()
*/
function hook_media_wysiwyg_format_form_prepare_alter(&$form, &$form_state, $file) {
$form['preview']['#access'] = FALSE;
$file = $form['#media'];
$form['heading']['#markup'] = t('Embedding %filename of type %filetype', array('%filename' => $file->filename, '%filetype' => $file->type));
}
/**
* Alter the output generated by Media filter tags.
*
* @param array $element
* The renderable array of output generated for the filter tag.
* @param array $tag_info
* The filter tag converted into an associative array by
* media_token_to_markup() with the following elements:
* - 'fid': The ID of the media file being rendered.
* - 'file': The object from file_load() of the media file being rendered.
* - 'view_mode': The view mode being used to render the file.
* - 'attributes': An additional array of attributes that could be output
* with media_get_file_without_label().
* @param array $settings
* An additional array of settings.
* - 'wysiwyg': A boolean if the output is for the WYSIWYG preview or FALSE
* if for normal rendering.