Issue #1073106 by scottrouse: Fixed 'Input Format' should be 'Text Format'.
[project/wysiwyg.git] / wysiwyg.admin.inc
index 6fda72b..05d47be 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-// $Id$
 
 /**
  * @file
@@ -7,41 +6,13 @@
  */
 
 /**
- * Callback handler for admin pages; menu callback.
- *
- * @todo Move into hook_menu(), resp. FAPI functions.
+ * Form builder for Wysiwyg profile form.
  */
-function wysiwyg_admin($arg = '', $format = '') {
-  switch ($arg) {
-    case 'edit':
-      if ($profile = wysiwyg_load_profile($format)) {
-        $breadcrumb = array();
-        $breadcrumb[] = l(t('Home'), NULL);
-        $breadcrumb[] = l(t('Administer'), 'admin');
-        $breadcrumb[] = l(t('Site configuration'), 'admin/settings');
-        $breadcrumb[] = l(t('Wysiwyg profiles'), 'admin/settings/wysiwyg/profile');
-        drupal_set_breadcrumb($breadcrumb);
-        return drupal_get_form('wysiwyg_profile_form', $profile);
-      }
-      break;
-
-    case 'delete':
-      return drupal_get_form('wysiwyg_profile_delete_confirm', $format);
-
-    case '':
-      return drupal_get_form('wysiwyg_profile_overview');
-  }
-  drupal_goto('admin/settings/wysiwyg/profile');
-}
-
-/**
- * Return an HTML form for profile configuration.
- */
-function wysiwyg_profile_form($form_state, $profile) {
+function wysiwyg_profile_form($form, &$form_state, $profile) {
   // Merge in defaults.
-  settype($profile, 'array');
+  $profile = (array) $profile;
   $profile += array(
-    'format' => 0,
+    'format' => '',
     'editor' => '',
   );
   if (empty($profile['settings'])) {
@@ -72,12 +43,12 @@ function wysiwyg_profile_form($form_state, $profile) {
     'css_path' => NULL,
     'css_classes' => NULL,
   );
-  settype($profile, 'object');
+  $profile = (object) $profile;
 
   $formats = filter_formats();
-  drupal_set_title(t('%format Wysiwyg profile', array('%format' => $formats[$profile->format]->name)));
+  $editor = wysiwyg_get_editor($profile->editor);
+  drupal_set_title(t('%editor profile for %format', array('%editor' => $editor['title'], '%format' => $formats[$profile->format]->name)), PASS_THROUGH);
 
-  $form = array();
   $form['format'] = array('#type' => 'value', '#value' => $profile->format);
   $form['input_format'] = array('#type' => 'value', '#value' => $formats[$profile->format]->name);
   $form['editor'] = array('#type' => 'value', '#value' => $profile->editor);
@@ -120,11 +91,24 @@ function wysiwyg_profile_form($form_state, $profile) {
 
   $form['basic']['language'] = array(
     '#type' => 'select',
-    '#title' => t('Language'),
+    '#title' => t('Interface language'),
     '#default_value' => $profile->settings['language'],
-    '#options' => drupal_map_assoc(array('ar', 'ca', 'cs', 'cy', 'da', 'de', 'el', 'en', 'es', 'fa', 'fi', 'fr', 'fr_ca', 'he', 'hu', 'is', 'it', 'ja', 'ko', 'nb', 'nl', 'nn', 'pl', 'pt', 'pt_br', 'ru', 'ru_KOI8-R', 'ru_UTF-8', 'si', 'sk', 'sv', 'th', 'zh_cn', 'zh_tw', 'zh_tw_utf8')),
-    '#description' => t('The language to use for the editor interface. Language codes are based on the <a href="http://www.loc.gov/standards/iso639-2/englangn.html">ISO-639-2</a> format.'),
   );
+  // @see _locale_prepare_predefined_list()
+  require_once DRUPAL_ROOT . '/includes/iso.inc';
+  $predefined = _locale_get_predefined_list();
+  foreach ($predefined as $key => $value) {
+    // Include native name in output, if possible
+    if (count($value) > 1) {
+      $tname = t($value[0]);
+      $predefined[$key] = ($tname == $value[1]) ? $tname : "$tname ($value[1])";
+    }
+    else {
+      $predefined[$key] = t($value[0]);
+    }
+  }
+  asort($predefined);
+  $form['basic']['language']['#options'] = $predefined;
 
   $form['buttons'] = array(
     '#type' => 'fieldset',
@@ -144,15 +128,15 @@ function wysiwyg_profile_form($form_state, $profile) {
         if (!empty($meta['path'])) {
           // @todo Button icon locations are different in editors, editor versions,
           //   and contrib/custom plugins (like Image Assist, f.e.).
-          $img_src = $meta['path'] ."/images/$name.gif";
+          $img_src = $meta['path'] . "/images/$name.gif";
           // Handle plugins that have more than one button.
           if (!file_exists($img_src)) {
-            $img_src = $meta['path'] ."/images/$button.gif";
+            $img_src = $meta['path'] . "/images/$button.gif";
           }
-          $icon = file_exists($img_src) ? '<img src="'. base_path() . $img_src .'" title="'. $button .'" style="border: 1px solid grey; vertical-align: middle;" />' : '';
+          $icon = file_exists($img_src) ? '<img src="' . base_path() . $img_src . '" title="' . $button . '" style="border: 1px solid grey; vertical-align: middle;" />' : '';
         }
-        $title = (isset($meta['url']) ? l($title, $meta['url'], array('target' => '_blank')) : $title);
-        $title = (!empty($icon) ? $icon .' '. $title : $title);
+        $title = (isset($meta['url']) ? l($title, $meta['url'], array('target' => '_blank')) : check_plain($title));
+        $title = (!empty($icon) ? $icon . ' ' . $title : $title);
         $form['buttons'][$name][$button] = array(
           '#type' => 'checkbox',
           '#title' => $title,
@@ -160,11 +144,11 @@ function wysiwyg_profile_form($form_state, $profile) {
         );
       }
     }
-    else if (isset($meta['extensions']) && is_array($meta['extensions'])) {
+    elseif (isset($meta['extensions']) && is_array($meta['extensions'])) {
       foreach ($meta['extensions'] as $extension => $title) {
         $form['buttons'][$name][$extension] = array(
           '#type' => 'checkbox',
-          '#title' => isset($meta['url']) ? l($title, $meta['url'], array('target' => '_blank')) : $title,
+          '#title' => isset($meta['url']) ? l($title, $meta['url'], array('target' => '_blank')) : check_plain($title),
           '#default_value' => !empty($profile->settings['buttons'][$name][$extension]) ? $profile->settings['buttons'][$name][$extension] : FALSE,
         );
       }
@@ -295,7 +279,7 @@ function wysiwyg_profile_form($form_state, $profile) {
     '#default_value' => $profile->settings['css_path'],
     '#size' => 40,
     '#maxlength' => 255,
-    '#description' => t('If "Define CSS" has been selected above, enter path to a CSS file or a list of CSS files seperated by a comma.') .'<br />'. t('Available tokens: %b (base path, f.e.: /), %t (path to theme, f.e.: themes/garland)') .'<br />'. t('Examples:') .' css/editor.css,/themes/garland/style.css,%b%t/style.css,http://example.com/external.css',
+    '#description' => t('If "Define CSS" was selected above, enter path to a CSS file or a list of CSS files separated by a comma.') . '<br />' . t('Available tokens: <code>%b</code> (base path, eg: <code>/</code>), <code>%t</code> (path to theme, eg: <code>themes/garland</code>)') . '<br />' . t('Example:') . ' css/editor.css,/themes/garland/style.css,%b%t/style.css,http://example.com/external.css',
   );
 
   $form['css']['css_classes'] = array(
@@ -308,6 +292,11 @@ function wysiwyg_profile_form($form_state, $profile) {
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Save'),
+    '#weight' => 100,
+  );
+  $form['cancel'] = array(
+    '#value' => l(t('Cancel'), 'admin/config/content/wysiwyg'),
+    '#weight' => 110,
   );
 
   return $form;
@@ -319,36 +308,49 @@ function wysiwyg_profile_form($form_state, $profile) {
  * @see wysiwyg_profile_form()
  */
 function wysiwyg_profile_form_submit($form, &$form_state) {
-  if (isset($form_state['values']['buttons'])) {
+  $values = $form_state['values'];
+  if (isset($values['buttons'])) {
     // Store only enabled buttons for each plugin.
-    foreach ($form_state['values']['buttons'] as $plugin => $buttons) {
-      $form_state['values']['buttons'][$plugin] = array_filter($form_state['values']['buttons'][$plugin]);
+    foreach ($values['buttons'] as $plugin => $buttons) {
+      $values['buttons'][$plugin] = array_filter($values['buttons'][$plugin]);
     }
     // Store only enabled plugins.
-    $form_state['values']['buttons'] = array_filter($form_state['values']['buttons']);
+    $values['buttons'] = array_filter($values['buttons']);
   }
+  // Remove any white-space from 'block_formats' setting, since editor
+  // implementations rely on a comma-separated list to explode().
+  $values['block_formats'] = preg_replace('@\s+@', '', $values['block_formats']);
+
   // Remove input format name.
-  $format = $form_state['values']['format'];
-  $input_format = $form_state['values']['input_format'];
-  $editor = $form_state['values']['editor'];
-  unset($form_state['values']['format'], $form_state['values']['input_format'], $form_state['values']['editor']);
+  $format = $values['format'];
+  $input_format = $values['input_format'];
+  $editor = $values['editor'];
+  unset($values['format'], $values['input_format'], $values['editor']);
 
   // Remove FAPI values.
   // @see system_settings_form_submit()
-  unset($form_state['values']['submit'], $form_state['values']['form_id'], $form_state['values']['op'], $form_state['values']['form_token']);
+  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($form_state['values']), $format);
+  db_merge('wysiwyg')
+    ->key(array('format' => $format))
+    ->fields(array(
+      'editor' => $editor,
+      'settings' => serialize($values),
+    ))
+    ->execute();
+  wysiwyg_profile_cache_clear();
 
   drupal_set_message(t('Wysiwyg profile for %format has been saved.', array('%format' => $input_format)));
 
-  drupal_goto('admin/settings/wysiwyg/profile');
+  $form_state['redirect'] = 'admin/config/content/wysiwyg';
 }
 
 /**
  * Layout for the buttons in the Wysiwyg Editor profile form.
  */
-function theme_wysiwyg_admin_button_table(&$form) {
+function theme_wysiwyg_admin_button_table($variables) {
+  $form = $variables['form'];
   $buttons = array();
 
   // Flatten forms array.
@@ -373,7 +375,7 @@ function theme_wysiwyg_admin_button_table(&$form) {
     $rows[] = $row;
   }
 
-  $output = theme('table', array(), $rows, array('width' => '100%'));
+  $output = theme('table', array('rows' => $rows, 'attributes' => array('width' => '100%')));
 
   return $output;
 }
@@ -381,79 +383,119 @@ function theme_wysiwyg_admin_button_table(&$form) {
 /**
  * Display overview of setup Wysiwyg Editor profiles; menu callback.
  */
-function wysiwyg_profile_overview() {
+function wysiwyg_profile_overview($form, &$form_state) {
   include_once './includes/install.inc';
-  $form = array();
 
   // Check which wysiwyg editors are installed.
   $editors = wysiwyg_get_all_editors();
   $count = count($editors);
   $status = array();
   $options = array('' => t('No editor'));
-  foreach ($editors as $editor => $properties) {
-    $status[$editor] = array(
-      'severity' => (isset($properties['error']) ? REQUIREMENT_ERROR : ($properties['installed'] ? REQUIREMENT_OK : REQUIREMENT_INFO)),
-      'title' => t('<a href="!vendor-url">@editor</a> (<a href="!download-url">Download</a>)', array('!vendor-url' => $properties['vendor url'], '@editor' => $properties['title'], '!download-url' => $properties['download url'])),
-      'value' => (isset($properties['installed version']) ? $properties['installed version'] : t('Not installed.')),
-      'description' => (isset($properties['error']) ? $properties['error'] : ($properties['installed'] ? '' : t('Extract the archive and copy its contents into a new folder in the following location:<br /><code>@editor-path</code>', array('@editor-path' => $properties['editor path'])))),
+
+  // D7's seven theme displays links in table headers as block elements.
+  drupal_add_css('table.system-status-report th a {display: inline;}', 'inline');
+
+  foreach ($editors as $name => $editor) {
+    $status[$name] = array(
+      'severity' => (isset($editor['error']) ? REQUIREMENT_ERROR : ($editor['installed'] ? REQUIREMENT_OK : REQUIREMENT_INFO)),
+      'title' => t('<a href="!vendor-url">@editor</a> (<a href="!download-url">Download</a>)', array('!vendor-url' => $editor['vendor url'], '@editor' => $editor['title'], '!download-url' => $editor['download url'])),
+      'value' => (isset($editor['installed version']) ? $editor['installed version'] : t('Not installed.')),
+      'description' => (isset($editor['error']) ? $editor['error'] : ''),
     );
-    if ($properties['installed']) {
-      $options[$editor] = $properties['title'] . (isset($properties['installed version']) ? ' ' . $properties['installed version'] : '');
+    if ($editor['installed']) {
+      $options[$name] = $editor['title'] . (isset($editor['installed version']) ? ' ' . $editor['installed version'] : '');
     }
     else {
+      // Build on-site installation instructions.
+      // @todo Setup $library in wysiwyg_load_editor() already.
+      $library = (isset($editor['library']) ? $editor['library'] : key($editor['libraries']));
+      $targs = array(
+        '@editor-path' => $editor['editor path'],
+        '@library-filepath' => $editor['library path'] . '/' . (isset($editor['libraries'][$library]['files'][0]) ? $editor['libraries'][$library]['files'][0] : key($editor['libraries'][$library]['files'])),
+      );
+      $instructions = '<p>' . t('Extract the archive and copy its contents into a new folder in the following location:<br /><code>@editor-path</code>', $targs) . '</p>';
+      $instructions .= '<p>' . t('So the actual library can be found at:<br /><code>@library-filepath</code>', $targs) . '</p>';
+
+      $status[$name]['description'] .= $instructions;
       $count--;
     }
+    // In case there is an error, always show installation instructions.
+    if (isset($editor['error'])) {
+      $show_instructions = TRUE;
+    }
+  }
+  if (!$count) {
+    $show_instructions = TRUE;
   }
   $form['status'] = array(
     '#type' => 'fieldset',
     '#title' => t('Installation instructions'),
     '#collapsible' => TRUE,
-    '#collapsed' => $count,
+    '#collapsed' => !isset($show_instructions),
     '#description' => (!$count ? t('There are no editor libraries installed currently. The following list contains a list of currently supported editors:') : ''),
     '#weight' => 10,
   );
-  $form['status']['report'] = array('#type' => 'markup', '#value' => theme('status_report', $status));
+  $form['status']['report'] = array('#markup' => theme('status_report', array('requirements' => $status)));
 
   if (!$count) {
     return $form;
   }
 
   $formats = filter_formats();
-  $profiles = wysiwyg_load_profile();
-  $form['formats']['#tree'] = TRUE;
+  $profiles = wysiwyg_profile_load_all();
+  $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,
+  );
+
+  $enable_save = FALSE;
   foreach ($formats as $id => $format) {
     $form['formats'][$id]['name'] = array(
-      '#value' => check_plain($format->name),
-    );
-    $form['formats'][$id]['editor'] = array(
-      '#type' => 'select',
-      '#default_value' => isset($profiles[$id]) ? $profiles[$id]->editor : '',
-      '#options' => $options,
-      '#id' => "edit-editor-$id",
+      '#markup' => check_plain($format->name),
     );
+    // Only display editor selection for associated input formats to avoid
+    // confusion about disabled selection.
+    if (isset($profiles[$id]) && !empty($profiles[$id]->editor)) {
+      $form['formats'][$id]['editor'] = array(
+        '#markup' => $options[$profiles[$id]->editor],
+      );
+    }
+    else {
+      $form['formats'][$id]['editor'] = array(
+        '#type' => 'select',
+        '#default_value' => '',
+        '#options' => $options,
+      );
+      $enable_save = TRUE;
+    }
     if (isset($profiles[$id]) && !empty($profiles[$id]->editor)) {
       $form['formats'][$id]['edit'] = array(
-        '#value' => l(t('Edit'), 'admin/settings/wysiwyg/profile/edit/'. $profiles[$id]->format),
+        '#markup' => l(t('Edit'), "admin/config/content/wysiwyg/profile/$id/edit"),
       );
-      $form['formats'][$id]['remove'] = array(
-        '#value' => l(t('Remove'), 'admin/settings/wysiwyg/profile/delete/'. $profiles[$id]->format),
+      $form['formats'][$id]['delete'] = array(
+        '#markup' => l(t('Delete'), "admin/config/content/wysiwyg/profile/$id/delete"),
       );
     }
   }
 
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+  // Submitting the form when no editors can be selected causes errors.
+  if ($enable_save) {
+    $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+  }
   return $form;
 }
 
 /**
  * Return HTML for the Wysiwyg profile overview form.
  */
-function theme_wysiwyg_profile_overview(&$form) {
+function theme_wysiwyg_profile_overview($variables) {
+  $form = $variables['form'];
   if (!isset($form['formats'])) {
     return;
   }
   $output = '';
-  $header = array(t('Input format'), t('Editor'), array('data' => t('Operations'), 'colspan' => 2));
+  $header = array(t('Text format'), t('Editor'), array('data' => t('Operations'), 'colspan' => 2));
   $rows = array();
   foreach (element_children($form['formats']) as $item) {
     $format = &$form['formats'][$item];
@@ -461,11 +503,11 @@ function theme_wysiwyg_profile_overview(&$form) {
       drupal_render($format['name']),
       drupal_render($format['editor']),
       isset($format['edit']) ? drupal_render($format['edit']) : '',
-      isset($format['remove']) ? drupal_render($format['remove']) : '',
+      isset($format['delete']) ? drupal_render($format['delete']) : '',
     );
   }
-  $output .= theme('table', $header, $rows);
-  $output .= drupal_render($form);
+  $form['formats']['table']['#markup'] = theme('table', array('header' => $header, 'rows' => $rows));
+  $output .= drupal_render_children($form);
   return $output;
 }
 
@@ -474,25 +516,27 @@ function theme_wysiwyg_profile_overview(&$form) {
  */
 function wysiwyg_profile_overview_submit($form, &$form_state) {
   foreach ($form_state['values']['formats'] as $format => $values) {
-    db_query("UPDATE {wysiwyg} SET editor = '%s' WHERE format = %d", $values['editor'], $format);
-    if (!db_affected_rows()) {
-      db_query("INSERT INTO {wysiwyg} (format, editor) VALUES (%d, '%s')", $format, $values['editor']);
-    }
+    db_merge('wysiwyg')
+      ->key(array('format' => $format))
+      ->fields(array(
+        'editor' => $values['editor'],
+      ))
+      ->execute();
   }
+  wysiwyg_profile_cache_clear();
 }
 
 /**
  * Delete editor profile confirmation form.
  */
-function wysiwyg_profile_delete_confirm(&$form_state, $format) {
-  $form = array();
-  $form['format'] = array('#type' => 'value', '#value' => $format);
+function wysiwyg_profile_delete_confirm($form, &$form_state, $profile) {
   $formats = filter_formats();
-  $form['name'] = array('#type' => 'value', '#value' => $formats[$format]->name);
+  $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' => $formats[$format]->name)),
-    'admin/settings/wysiwyg/profile',
+    t('Are you sure you want to remove the profile for %name?', array('%name' => $format->name)),
+    'admin/config/content/wysiwyg',
     t('This action cannot be undone.'), t('Remove'), t('Cancel')
   );
 }
@@ -503,15 +547,11 @@ function wysiwyg_profile_delete_confirm(&$form_state, $format) {
  * @see wysiwyg_profile_delete_confirm()
  */
 function wysiwyg_profile_delete_confirm_submit($form, &$form_state) {
-  wysiwyg_profile_delete($form_state['values']['format']);
-  drupal_set_message(t('Wysiwyg profile for %name has been deleted.', array('%name' => $form_state['values']['name'])));
-  $form_state['redirect'] = 'admin/settings/wysiwyg/profile';
-}
+  $format = $form_state['values']['format'];
+  wysiwyg_profile_delete($format->format);
+  wysiwyg_profile_cache_clear();
 
-/**
- * Remove a profile from the database.
- */
-function wysiwyg_profile_delete($format) {
-  db_query("DELETE FROM {wysiwyg} WHERE format = %d", $format);
+  drupal_set_message(t('Wysiwyg profile for %name has been deleted.', array('%name' => $format->name)));
+  $form_state['redirect'] = 'admin/config/content/wysiwyg';
 }