Index: wysiwyg.admin.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/wysiwyg.admin.inc,v retrieving revision 1.15.2.9 diff -u -p -r1.15.2.9 wysiwyg.admin.inc --- wysiwyg.admin.inc 13 Feb 2010 23:58:41 -0000 1.15.2.9 +++ wysiwyg.admin.inc 9 Jun 2010 18:58:48 -0000 @@ -316,7 +316,18 @@ function wysiwyg_profile_form_submit($fo unset($values['submit'], $values['form_id'], $values['op'], $values['form_token'], $values['form_build_id']); // Insert new profile data. - db_query("UPDATE {wysiwyg} SET settings = '%s' WHERE format = %d", serialize($values), $format); + // Determine if this is an update. + if (!db_result(db_query("SELECT 1 FROM {wysiwyg} WHERE format = %d", $format))) { + $update = array(); + } + else { + $update = array('format'); + } + $wysiwyg = new stdClass(); + $wysiwyg->format = $format; + $wysiwyg->editor = $editor; + $wysiwyg->settings = serialize($values); + drupal_write_record('wysiwyg', $wysiwyg, $update); drupal_set_message(t('Wysiwyg profile for %format has been saved.', array('%format' => $input_format))); @@ -415,13 +426,15 @@ function wysiwyg_profile_overview() { } $formats = filter_formats(); - $profiles = wysiwyg_profile_load_all(); + // Reset wysiwyg cache + $profiles = wysiwyg_profile_load_all(TRUE); $form['formats'] = array( '#type' => 'item', '#description' => t('To assign a different editor to a text format, click "delete" to remove the existing first.'), '#tree' => TRUE, ); + $ctools_installed = module_exists('ctools'); $enable_save = FALSE; foreach ($formats as $id => $format) { $form['formats'][$id]['name'] = array( @@ -443,12 +456,31 @@ function wysiwyg_profile_overview() { $enable_save = TRUE; } if (isset($profiles[$id]) && !empty($profiles[$id]->editor)) { - $form['formats'][$id]['edit'] = array( - '#value' => l(t('Edit'), "admin/settings/wysiwyg/profile/$id/edit"), - ); - $form['formats'][$id]['delete'] = array( - '#value' => l(t('Delete'), "admin/settings/wysiwyg/profile/$id/delete"), - ); + if (isset($profiles[$id]->default)) { + $form['formats'][$id]['edit'] = array( + '#value' => l(t('Override'), "admin/settings/wysiwyg/profile/$id/edit"), + ); + } + else { + $form['formats'][$id]['edit'] = array( + '#value' => l(t('Edit'), "admin/settings/wysiwyg/profile/$id/edit"), + ); + } + if ($ctools_installed) { + $form['formats'][$id]['export'] = array( + '#value' => l(t('Export'), "admin/settings/wysiwyg/profile/$id/export"), + ); + } + if (isset($profiles[$id]->default)) { + $form['formats'][$id]['delete'] = array( + '#value' => l(t('Revert'), "admin/settings/wysiwyg/profile/$id/revert"), + ); + } + else { + $form['formats'][$id]['delete'] = array( + '#value' => l(t('Delete'), "admin/settings/wysiwyg/profile/$id/delete"), + ); + } } } @@ -456,10 +488,115 @@ function wysiwyg_profile_overview() { if ($enable_save) { $form['submit'] = array('#type' => 'submit', '#value' => t('Save')); } + if (!$ctools_installed) { + drupal_set_message(t('If you install !ctools module, you will be able to export and import wysiwyg profiles.', array('!ctools' => l('CTools', 'http://drupal.org/project/ctools'))), 'status'); + } return $form; } /** + * Import a format setting. + */ +function wysiwyg_import_profile_page(&$form_state) { + if (module_exists('ctools')) { + $format_objs = filter_formats(); + $formats[0] = t('As defined in the import'); + foreach ($format_objs as $obj) { + $formats[$obj->format] = $obj->name; + } + + $form['wysiwyg'] = array( + '#type' => 'textarea', + '#title' => t('Paste wysiwyg settings code here'), + '#required' => TRUE, + ); + + $form['target_format'] = array( + '#type' => 'select', + '#title' => t('Target format'), + '#options' => $formats, + '#description' => t('Input format for the wysiwyg settings'), + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Import'), + '#submit' => array('wysiwyg_import_submit'), + '#validate' => array('wysiwyg_import_validate'), + ); + + return $form; + } + else { + form_set_error('', t('You need to install the !ctools module to be able to export and import wysiwyg profiles.', array('!ctools' => l('Ctools', 'http://drupal.org/project/ctools')))); + return array(); + } +} + +/** + * Validate that the pasted in code works. + */ +function wysiwyg_import_validate($form, &$form_state) { + $wysiwyg = ''; + // Put any necessary includes here + ob_start(); + eval($form_state['values']['wysiwyg']); + ob_end_clean(); + + if (!is_object($wysiwyg)) { + return form_error($form['wysiwyg'], t('Unable to interpret wysiwyg code.')); + } + if (empty($wysiwyg->api_version) || $wysiwyg->api_version < 2) { + form_error($form['wysiwyg'], t('That wysiwyg format setting is not compatible with this version of the wysiwyg module.')); + } + + + if ($form_state['values']['target_format']) { + $wysiwyg->format = $form_state['values']['target_format']; + } + drupal_alter('wysiwyg_import_profile', $wysiwyg); + + // Refuse any settings that already exist for that format type + $profile_exists = db_result(db_query("SELECT format FROM {wysiwyg} WHERE format = %d AND settings IS NOT NULL", $wysiwyg->format)); + if ($profile_exists) { + form_error($form['wysiwyg'], t('Wysiwyg settings already exists for that input format type. Please delete the existing settings and attempt the import again if you wish to replace the existing settings.')); + } +} + +/** + * Submit handler for wysiwyg settings import + */ +function wysiwyg_import_submit($form, &$form_state) { + // Check to see if the setting exits (should have been caught by validation hook above); if so give an error; + // else write the format settings to the database and then redirect the user to the edit page + $wysiwyg = ''; + eval($form_state['values']['wysiwyg']); + + if ($form_state['values']['target_format']) { + $wysiwyg->format = $form_state['values']['target_format']; + } + + // Write the settings to the database + $wysiwyg->settings = serialize($wysiwyg->settings); + drupal_alter('wysiwyg_import_profile', $wysiwyg); + + $settings_exists = db_result(db_query("SELECT 1 FROM {wysiwyg} WHERE format = %d", $wysiwyg->format)); + if ($settings_exists) { + drupal_set_message(t('Settings for that format input type already exists; your import was not used and nothing was done. Please delete the existing wysiwyg format settings for that input type and import again.'), 'error'); + return; + } + + $dwr_ret = drupal_write_record('wysiwyg', $wysiwyg); + + if ($dwr_ret === FALSE) { + drupal_set_message(t('An error occurred when writing the wysiwyg settings to the database.') , 'error'); + return; + } + drupal_set_message(t('Wysiwyg settings were imported successfully.')); + $form_state['redirect'] = 'admin/settings/wysiwyg/profile/'. $wysiwyg->format .'/edit'; +} + +/** * Return HTML for the Wysiwyg profile overview form. */ function theme_wysiwyg_profile_overview($form) { @@ -467,7 +604,7 @@ function theme_wysiwyg_profile_overview( return; } $output = ''; - $header = array(t('Input format'), t('Editor'), array('data' => t('Operations'), 'colspan' => 2)); + $header = array(t('Input format'), t('Editor'), array('data' => t('Operations'), 'colspan' => 3)); $rows = array(); foreach (element_children($form['formats']) as $item) { $format = &$form['formats'][$item]; @@ -475,6 +612,7 @@ function theme_wysiwyg_profile_overview( drupal_render($format['name']), drupal_render($format['editor']), isset($format['edit']) ? drupal_render($format['edit']) : '', + isset($format['export']) ? drupal_render($format['export']) : '', isset($format['delete']) ? drupal_render($format['delete']) : '', ); } @@ -498,27 +636,29 @@ function wysiwyg_profile_overview_submit /** * Delete editor profile confirmation form. */ -function wysiwyg_profile_delete_confirm(&$form_state, $profile) { +function wysiwyg_profile_revert_confirm(&$form_state, $profile) { $formats = filter_formats(); $format = $formats[$profile->format]; $form['format'] = array('#type' => 'value', '#value' => $format); return confirm_form( $form, - t('Are you sure you want to remove the profile for %name?', array('%name' => $format->name)), + t('Are you sure you want to revert the profile\'s settings for %name?', array('%name' => $format->name)), 'admin/settings/wysiwyg', - t('This action cannot be undone.'), t('Remove'), t('Cancel') + t('This action cannot be undone.'), t('Revert'), t('Cancel') ); + } /** * Submit callback for Wysiwyg profile delete form. * - * @see wysiwyg_profile_delete_confirm() + * @see wysiwyg_profile_revert_confirm() */ -function wysiwyg_profile_delete_confirm_submit($form, &$form_state) { +function wysiwyg_profile_revert_confirm_submit($form, &$form_state) { $format = $form_state['values']['format']; + // Delete settings from database, they will be rebuilded from code. wysiwyg_profile_delete($format->format); - drupal_set_message(t('Wysiwyg profile for %name has been deleted.', array('%name' => $format->name))); + drupal_set_message(t('Wysiwyg profile settings for %name has been reverted.', array('%name' => $format->name))); $form_state['redirect'] = 'admin/settings/wysiwyg'; } @@ -528,4 +668,3 @@ function wysiwyg_profile_delete_confirm_ function wysiwyg_profile_delete($format) { db_query("DELETE FROM {wysiwyg} WHERE format = %d", $format); } - Index: wysiwyg.features.inc =================================================================== RCS file: wysiwyg.features.inc diff -N wysiwyg.features.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ wysiwyg.features.inc 9 Jun 2010 18:58:49 -0000 @@ -0,0 +1,100 @@ + $wysiwyg_profile) { + if ($wysiwyg_profile->editor) { + $labels[$id] = t('@format (@editor)', array('@editor' => $wysiwyg_profile->editor, '@format' => $filter_formats[$id]->name)); + } + } + } + return $labels; +} + +/** + * Implementation of hook_features_export(). + */ +function wysiwyg_features_export($data, &$export, $module_name = '') { + + $return = ctools_component_features_export('wysiwyg', $data, $export, $module_name); + + // Allow other modules to add more dependencies. + // Only the first paramaeter is passed by reference in drupal_alter + drupal_alter('wysiwyg_features_export', $export, $data, $module_name); + + return $return; +} + +/** + * Implementation of hook_features_export_render(). + */ +function wysiwyg_features_export_render($module = "foo", $data) { + // This is basically equal to ctools_export_object_render() + $component = 'wysiwyg'; + + ctools_include('export'); + + $schema = ctools_export_get_schema($component); + + $code = ' $export = array();'."\n"; + foreach ($data as $object) { + $identifier = $schema['export']['identifier']; + $objects = ctools_export_load_object($component, 'names', array($object)); + if (!empty($objects[$object])) { + // Support objects that have a defined export callback, but fall back to. + // ctools_export_object(). + if (function_exists($schema['export']['export callback'])) { + $code .= $schema['export']['export callback']($objects[$object], ' '); + } + else { + $code .= ctools_export_object($component, $objects[$object], ' ', $identifier); + } + $code .= "\n"; + // Use $xport[$wysiwyg->format] instead of $export[$object] + // $wysiwyg->format can be modified implementing hook_wysiwyg_export_profile_alter + $code .= ' $export[$'. $identifier . '->format] = $'. $identifier .';'."\n"; + } + + $code .= ' return $export;'; + } + + return array($schema['export']['default hook'] => $code); +} + +/** + * Implementation of hook_features_revert(). + */ +function wysiwyg_features_revert($module) { + $component = 'wysiwyg'; + $objects = module_invoke($module, 'wysiwyg_defaults'); + drupal_alter('wysiwyg_features_revert', $objects); + if (!empty($objects)) { + $schema = ctools_export_get_schema($component); + $export = $schema['export']; + $names = db_placeholders(array_keys($objects), $schema['fields'][$export['key']]['type']); + db_query("DELETE FROM {{$component}} WHERE {$export['key']} IN ({$names})", array_keys($objects)); + } + // Ensure cache is cleared + wysiwyg_profile_load_all(TRUE); +} Index: wysiwyg.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/wysiwyg.install,v retrieving revision 1.4.2.2 diff -u -p -r1.4.2.2 wysiwyg.install --- wysiwyg.install 13 Feb 2010 23:58:41 -0000 1.4.2.2 +++ wysiwyg.install 9 Jun 2010 18:58:49 -0000 @@ -7,6 +7,19 @@ function wysiwyg_schema() { $schema['wysiwyg'] = array( 'description' => t('Stores Wysiwyg profiles.'), + 'export' => array( + 'key' => 'format', + 'identifier' => 'wysiwyg', + 'default hook' => 'wysiwyg_defaults', // Function hook name. + 'export callback' => 'wysiwyg_export_profile', + 'export module' => 'wysiwyg', + 'api' => array( + 'owner' => 'wysiwyg', + 'api' => 'wysiwyg_defaults', // Base name for api include files. + 'minimum_version' => 2, + 'current_version' => 2, + ), + ), 'fields' => array( 'format' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), 'editor' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''), Index: wysiwyg.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/wysiwyg.module,v retrieving revision 1.33.2.11 diff -u -p -r1.33.2.11 wysiwyg.module --- wysiwyg.module 14 Feb 2010 01:59:47 -0000 1.33.2.11 +++ wysiwyg.module 9 Jun 2010 18:58:51 -0000 @@ -50,6 +50,33 @@ function wysiwyg_menu() { 'type' => MENU_CALLBACK, 'file' => 'wysiwyg.dialog.inc', ); + $items['admin/settings/wysiwyg/profile/%/export'] = array( + 'title' => 'Export', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('wysiwyg_export_profile_page', 4), + 'access arguments' => array('administer filters'), + 'type' => MENU_CALLBACK, + ); + $items['admin/settings/wysiwyg/import'] = array( + 'title' => 'Import', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('wysiwyg_import_profile_page', 3), + 'access arguments' => array('import wysiwyg profiles'), + 'file' => 'wysiwyg.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 10 + ); + $items['admin/settings/wysiwyg/profile/%wysiwyg_profile/revert'] = array( + 'title' => 'Revert', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('wysiwyg_profile_revert_confirm', 4), + 'access arguments' => array('administer filters'), + 'file' => 'wysiwyg.admin.inc', + 'tab_root' => 'admin/settings/wysiwyg/profile', + 'tab_parent' => 'admin/settings/wysiwyg/profile/%wysiwyg_profile', + 'type' => MENU_LOCAL_TASK, + 'weight' => 10, + ); return $items; } @@ -87,6 +114,20 @@ function wysiwyg_help($path, $arg) { } /** + * Implementation of hook_perm(). + */ +function wysiwyg_perm() { + return array('import wysiwyg profiles'); +} + +/** + * Clear wysiwyg cache on admin/build/modules form. + */ +function wysiwyg_form_system_modules_alter(&$form, $form_state) { + wysiwyg_profile_load_all(TRUE); +} + +/** * Implementation of hook_form_alter(). * * Before Drupal 7, there is no way to easily identify form fields that are @@ -585,12 +626,9 @@ function wysiwyg_get_css() { function wysiwyg_profile_load($format) { static $profiles; + // If the profile is marked as default, check if it has overrides from the database if (!isset($profiles) || !array_key_exists($format, $profiles)) { - $result = db_query('SELECT format, editor, settings FROM {wysiwyg} WHERE format = %d', $format); - while ($profile = db_fetch_object($result)) { - $profile->settings = unserialize($profile->settings); - $profiles[$profile->format] = $profile; - } + $profiles = wysiwyg_profile_load_all(); } return (isset($profiles[$format]) ? $profiles[$format] : FALSE); @@ -599,16 +637,32 @@ function wysiwyg_profile_load($format) { /** * Load all profiles. */ -function wysiwyg_profile_load_all() { +function wysiwyg_profile_load_all($reset = FALSE) { static $profiles; - if (!isset($profiles)) { + if ($reset || !isset($profiles)) { $profiles = array(); + if (!$reset && ($cache = cache_get('wysiwyg:profiles', 'cache')) && is_array($cache->data)) { + $profiles = $cache->data; + return $profiles; + } + + // Load first wysiwyg settings from code, calling to hook_wysiwyg_defaults + $default_profiles = module_invoke_all('wysiwyg_defaults'); + foreach ($default_profiles as $default_profile) { + $default_profile->default = TRUE; + $profiles[$default_profile->format] = $default_profile; + } + + // Now, load settings from the database. + // They will override settings from code, if any $result = db_query('SELECT format, editor, settings FROM {wysiwyg}'); while ($profile = db_fetch_object($result)) { $profile->settings = unserialize($profile->settings); $profiles[$profile->format] = $profile; } + drupal_alter('wysiwyg_load_profiles', $profiles); + cache_set('wysiwyg:profiles', $profiles); } return $profiles; @@ -971,3 +1025,74 @@ function _wysiwyg_process_include($modul * @} End of "defgroup wysiwyg_api". */ +/** + * @defgroup wysiwyg_export_import Wysiwyg Export Import + * + * @{ + */ + +/** + * Export a format setting and display it in a form. + */ +function wysiwyg_export_profile_page(&$form_state, $format) { + if (module_exists('ctools')) { + $obj = wysiwyg_profile_load($format); + + $formats = filter_formats(); + $format_name = $formats[$format]->name; + + drupal_set_title(t('Export @wysiwyg settings for: @format input format', array('@wysiwyg'=> $obj->editor, '@format' => $format_name))); + $code = wysiwyg_export_profile($obj); + + $form['export'] = array( + '#title' => t('Export data'), + '#type' => 'textarea', + '#value' => $code, + '#rows' => 15, + '#description' => t('Copy the export text and paste it into another wysiwyg format using the import function.'), + ); + return $form; + } + else { + form_set_error('', t('You need to install the !ctools module to be able to export and import wysiwyg profiles.', array('!ctools' => l('Ctools', 'http://drupal.org/project/ctools')))); + return array(); + } +} + +/** + * Export wysiwyg settings. + */ +function wysiwyg_export_profile($obj, $indent = '') { + ctools_include('export'); + if (is_string($obj->settings)) { + $obj->settings = unserialize($obj->settings); + } + else { + $obj->settings = $obj->settings; + } + $additions = array(); + drupal_alter('wysiwyg_export_profile', $additions, $obj); + return ctools_export_object('wysiwyg', $obj, $indent, NULL, array(), $additions); +} + +/** + * Implementation of hook_features_api(). + */ +function wysiwyg_features_api() { + if (!module_exists('ctools')) { + return array(); + } + return array( + 'wysiwyg' => array( + 'name' => t('Wysiwyg Profiles'), + 'default_hook' => 'wysiwyg_defaults', + 'default_file' => FEATURES_DEFAULTS_INCLUDED, + 'features_source' => TRUE, + 'file' => drupal_get_path('module', 'wysiwyg') .'/wysiwyg.features.inc', + ), + ); +} + +/** + * @} End of "defgroup wysiwyg_export_import". + */