You are here

tinymce.module in TinyMCE 6

Integrate the TinyMCE editor (http://tinymce.moxiecode.com/) into Drupal.

File

tinymce.module
View source
<?php

// A collaborative project by Matt Westgate <drupal at asitis dot org>,
// Richard Bennett <richard.b@ at ritechnologies dot com> and Jeff Robbins <robbins at jjeff dot com>

/**
 * @file
 * Integrate the TinyMCE editor (http://tinymce.moxiecode.com/) into Drupal.
 */

/**
 * Implementation of hook_menu().
 */
function tinymce_menu() {
  $items['admin/settings/tinymce'] = array(
    'title' => 'TinyMCE',
    'description' => 'Configure the rich editor.',
    'page callback' => 'tinymce_admin',
    'access arguments' => array(
      'administer tinymce',
    ),
    'file' => 'tinymce.admin.inc',
  );
  return $items;
}

/**
 * Implementation of hook_theme()
 */
function tinymce_theme() {
  return array(
    // This button table is used in TinyMCE admininstration.
    'tinymce_admin_button_table' => array(
      'arguments' => array(
        'form',
      ),
    ),
    'tinymce_theme' => array(
      'arguments' => array(
        'init',
        'textarea_name',
        'theme_name',
        'is_running',
      ),
    ),
  );
}

/**
 * Implementation of hook_help().
 */
function tinymce_help($path, $arg) {
  switch ($path) {
    case 'admin/settings/tinymce#pages':
      return "node/*\nuser/*\ncomment/*";
    case 'admin/settings/tinymce':
    case 'admin/help#tinymce':
      return t('<p style="font-size:x-small">$Revision$ $Date$</p>' . '<p>TinyMCE adds what-you-see-is-what-you-get (WYSIWYG) html editing to textareas. This editor can be enabled/disabled without reloading the page by clicking a link below each textarea.</p>
                <p>Profiles can be defined based on user roles. A TinyMCE profile can define which pages receive this TinyMCE capability, what buttons or themes are enabled for the editor, how the editor is displayed, and a few other editor functions.</p>
                <p>Lastly, only users with the <code>access tinymce</code> <a href="!url">permission</a> will be able to use TinyMCE.</p>', array(
        '!url' => url('admin/user/permissions'),
      ));
  }
}

/**
 * Implementation of hook_perm().
 */
function tinymce_perm() {
  $array = array(
    'administer tinymce',
    'access tinymce',
  );
  $tinymce_mod_path = drupal_get_path('module', 'tinymce');
  if (is_dir($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/imagemanager/')) {
    $array[] = 'access tinymce imagemanager';
  }
  if (is_dir($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/filemanager/')) {
    $array[] = 'access tinymce filemanager';
  }
  return $array;
}

/**
 * Implementation of hook_elements().
 */
function tinymce_elements() {
  $type = array();
  if (user_access('access tinymce')) {

    // Let TinyMCE potentially process each textarea.
    $type['textarea'] = array(
      '#process' => array(
        'tinymce_process_textarea',
      ),
    );
  }
  return $type;
}

/**
 * Implementation of hook_form_alter()
 */
function tinymce_form_alter(&$form, &$form_state) {

  // disable 'teaser' textarea
  unset($form['body_field']['teaser_js']);
  $form['body_field']['teaser_include'] = array();
}

/**
 * Attach tinymce to a textarea
 */
function tinymce_process_textarea($element) {
  static $is_running = FALSE;
  global $user;
  static $profile_name;

  //$element is an array of attributes for the textarea but there is no just 'name' value, so we extract this from the #id field
  $textarea_name = substr($element['#id'], strpos($element['#id'], '-') + 1);

  // Since tinymce_config() makes a db hit, only call it when we're pretty sure
  // we're gonna render tinymce.
  if (!$profile_name) {
    $profile_name = db_result(db_query('SELECT s.name FROM {tinymce_settings} s INNER JOIN {tinymce_role} r ON r.name = s.name WHERE r.rid IN (%s)', implode(',', array_keys($user->roles))));
    if (!$profile_name) {
      return $element;
    }
  }
  $profile = tinymce_profile_load($profile_name);
  $init = tinymce_config($profile);
  $init['elements'] = 'edit-' . $textarea_name;
  if (_tinymce_page_match($profile)) {

    // Merge user-defined TinyMCE settings.
    $init = (array) theme('tinymce_theme', $init, $textarea_name, $init['theme'], $is_running);

    // If $init array is empty no need to execute rest of code since there are no textareas to theme with TinyMCE
    if (count($init) < 1) {
      return $element;
    }
    $settings = array();
    foreach ($init as $k => $v) {
      $v = is_array($v) ? implode(',', $v) : $v;

      // Don't wrap the JS init in quotes for boolean values or functions.
      if (strtolower($v) != 'true' && strtolower($v) != 'false' && $v[0] != '{') {
        $v = '"' . $v . '"';
      }
      $settings[] = $k . ' : ' . $v;
    }
    $tinymce_settings = implode(",\n    ", $settings);
    $enable = t('enable rich-text');
    $disable = t('disable rich-text');
    $tinymce_invoke = <<<EOD

  tinyMCE.init({
    {<span class="php-variable">$tinymce_settings</span>}
  });

EOD;
    $tinymce_gz_invoke = <<<EOD

  tinyMCE_GZ.init({
    {<span class="php-variable">$tinymce_settings</span>}
  });

EOD;
    $js_toggle = <<<EOD

  function mceToggle(id, linkid) {
    element = document.getElementById(id);
    link = document.getElementById(linkid);
    img_assist = document.getElementById('img_assist-link-'+ id);

    if (tinyMCE.get(element.id) == null) {
      tinyMCE.execCommand('mceAddControl',false,element.id);
      element.togg = 'on';
      link.innerHTML = '{<span class="php-variable">$disable</span>}';
      link.href = "javascript:mceToggle('" +id+ "', '" +linkid+ "');";
      if (img_assist)
        img_assist.innerHTML = '';
      link.blur();
    }
    else {
      tinyMCE.execCommand('mceRemoveControl',false,element.id);
      element.togg = 'off';
      link.innerHTML = '{<span class="php-variable">$enable</span>}';
      link.href = "javascript:mceToggle('" +id+ "', '" +linkid+ "');";
      if (img_assist)
        img_assist.innerHTML = img_assist_default_link;
      link.blur();
    }
  }

EOD;
    $status = tinymce_user_get_status($user, $profile);

    // note we test for string == true because we save our settings as strings
    $link_text = $status == 'true' ? $disable : $enable;
    $img_assist_link = $status == 'true' ? 'yes' : 'no';
    $no_wysiwyg = t('Your current web browser does not support WYSIWYG editing.');
    $wysiwyg_link = <<<EOD
<script type="text/javascript">
  img_assist = document.getElementById('img_assist-link-edit-{<span class="php-variable">$textarea_name</span>}');
  if (img_assist) {
    var img_assist_default_link = img_assist.innerHTML;
    if ('{<span class="php-variable">$img_assist_link</span>}' == 'yes') {
      img_assist.innerHTML = tinyMCE.get('edit-{<span class="php-variable">$textarea_name</span>}') == null ? '' : img_assist_default_link;
    }
    else {
      img_assist.innerHTML = tinyMCE.get('edit-{<span class="php-variable">$textarea_name</span>}') == null ? img_assist_default_link : '';
    }
  }
  if (typeof(document.execCommand) == 'undefined') {
    img_assist.innerHTML = img_assist_default_link;
    document.write('<div style="font-size:x-small">{<span class="php-variable">$no_wysiwyg</span>}</div>');
  }
  else {
    document.write("<div><a href=\\"javascript:mceToggle('edit-{<span class="php-variable">$textarea_name</span>}', 'wysiwyg4{<span class="php-variable">$textarea_name</span>}');\\" id=\\"wysiwyg4{<span class="php-variable">$textarea_name</span>}\\">{<span class="php-variable">$link_text</span>}</a></div>");
  }
</script>
EOD;

    // We only load the TinyMCE js file once per request
    if (!$is_running) {
      $is_running = TRUE;
      $tinymce_mod_path = drupal_get_path('module', 'tinymce');
      if (is_dir($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/imagemanager/') && user_access('access tinymce imagemanager')) {

        // if tinymce imagemanager is installed
        drupal_add_js($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/imagemanager/jscripts/mcimagemanager.js');
      }
      if (is_dir($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/filemanager/') && user_access('access tinymce filemanager')) {

        // if tinymce filemanager is installed
        drupal_add_js($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/filemanager/jscripts/mcfilemanager.js');
      }

      // Add integration with IMCE if available.
      if (module_exists('imce') && imce_access()) {
        drupal_add_js("function mceImageBrowser(fid, url, type, win) { win.open(Drupal.settings.basePath + '?q=imce&app=TinyMCE|url@'+ fid, '', 'width=760, height=560, resizable=1'); }", 'inline');
      }

      // TinyMCE Compressor 1.0.9 and greater
      if (file_exists($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/tiny_mce_gzip.js')) {
        drupal_add_js($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/tiny_mce_gzip.js');
        drupal_add_js($tinymce_gz_invoke, 'inline');
      }
      elseif (file_exists($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/tiny_mce_gzip.php')) {
        drupal_add_js($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/tiny_mce_gzip.php');
      }
      else {

        // For some crazy reason IE will only load this JS file if the absolute reference is given to it.
        drupal_add_js($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/tiny_mce.js');
      }
      drupal_add_js($js_toggle, 'inline');

      // We have to do this becuase of some unfocused CSS in certain themes. See http://drupal.org/node/18879 for details
      drupal_set_html_head('<style type="text/css" media="all">.mceEditor img { display: inline; }</style>');
    }

    // Load a TinyMCE init for each textarea.
    if ($init) {
      drupal_add_js($tinymce_invoke, 'inline');
    }

    //settings are saved as strings, not booleans
    if ($profile->settings['show_toggle'] == 'true') {

      // Make sure to append to #suffix so it isn't completely overwritten
      $element['#suffix'] .= $wysiwyg_link;
    }

    // Set resizable to false to avoid drupal.js resizable function from taking control of the textarea
    $element['#resizable'] = FALSE;
  }
  return $element;
}

/**
 * Implementation of hook_user().
 */
function tinymce_user($type, &$edit, &$user, $category = NULL) {
  if ($type == 'form' && $category == 'account' && user_access('access tinymce')) {
    $profile = tinymce_user_get_profile($user);

    // because the settings are saved as strings we need to test for the string 'true'
    if ($profile->settings['user_choose'] == 'true') {
      $form['tinymce'] = array(
        '#type' => 'fieldset',
        '#title' => t('TinyMCE rich-text settings'),
        '#weight' => 10,
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
      );
      $form['tinymce']['tinymce_status'] = array(
        '#type' => 'select',
        '#title' => t('Default state'),
        '#default_value' => isset($user->tinymce_status) ? $user->tinymce_status : (isset($profile->settings['default']) ? $profile->settings['default'] : 'false'),
        '#options' => array(
          'false' => t('disabled'),
          'true' => t('enabled'),
        ),
        '#description' => t('Should rich-text editing be enabled or disabled by default in textarea fields?'),
      );
      return array(
        'tinymce' => $form,
      );
    }
  }
  if ($type == 'validate') {
    return array(
      'tinymce_status' => $edit['tinymce_status'],
    );
  }
}

/**
 * @addtogroup themeable
 * @{
 */

/**
 * Customize a TinyMCE theme.
 *
 * @param init
 *   An array of settings TinyMCE should invoke a theme. You may override any
 *   of the TinyMCE settings. Details here:
 *
 *    http://tinymce.moxiecode.com/wrapper.php?url=tinymce/docs/using.htm
 *
 * @param textarea_name
 *   The name of the textarea TinyMCE wants to enable.
 *
 * @param theme_name
 *   The default tinymce theme name to be enabled for this textarea. The
 *   sitewide default is 'simple', but the user may also override this.
 *
 * @param is_running
 *   A boolean flag that identifies id TinyMCE is currently running for this
 *   request life cycle. It can be ignored.
 */
function theme_tinymce_theme($init, $textarea_name, $theme_name, $is_running) {

  // uncomment to debug this

  /*   print_r($init);
      print_r($textarea_name);
      print_r($theme_name);
      print_r($is_running);
  */
  switch ($textarea_name) {

    // Disable tinymce for these textareas
    case 'log':

    // book and page log
    case 'img_assist_pages':
    case 'caption':

    // signature
    case 'pages':
    case 'access_pages':

    //TinyMCE profile settings.
    case 'user_mail_welcome_body':

    // user config settings
    case 'user_mail_approval_body':

    // user config settings
    case 'user_mail_pass_body':

    // user config settings
    case 'synonyms':

    // taxonomy terms
    case 'description':

      // taxonomy terms
      unset($init);
      break;

    // Force the 'simple' theme for some of the smaller textareas.
    case 'signature':
    case 'site_mission':
    case 'site_footer':
    case 'site_offline_message':
    case 'page_help':
    case 'user_registration_help':
    case 'user_picture_guidelines':
      $init['theme'] = 'simple';
      foreach ($init as $k => $v) {
        if (strstr($k, 'theme_advanced_')) {
          unset($init[$k]);
        }
      }
      break;
  }

  /* Example, add some extra features when using the advanced theme.

    // If $init is available, we can extend it
    if (isset($init)) {
      switch ($theme_name) {
       case 'advanced':
         $init['extended_valid_elements'] = array('a[href|target|name|title|onclick]');
         break;
      }
    }

    */

  // Always return $init
  return $init;
}

/** @} End of addtogroup themeable */

/**
 * Grab the themes available to TinyMCE.
 *
 * TinyMCE themes control the functionality and buttons that are available to a
 * user. Themes are only looked for within the default TinyMCE theme directory.
 *
 * NOTE: This function is not used in this release. We are only using advanced theme.
 *
 * @return
 *   An array of theme names.
 */
function _tinymce_get_themes() {
  static $themes = array();
  if (!$themes) {
    $theme_loc = drupal_get_path('module', 'tinymce') . '/tinymce/jscripts/tiny_mce/themes/';
    if (is_dir($theme_loc) && ($dh = opendir($theme_loc))) {
      while (($file = readdir($dh)) !== FALSE) {
        if (!in_array($file, array(
          '.',
          '..',
          'CVS',
        )) && is_dir($theme_loc . $file)) {
          $themes[$file] = $file;
        }
      }
      closedir($dh);
      asort($themes);
    }
  }
  return $themes;
}

/**
 * Return plugin metadata from the plugin registry.
 *
 * We also scrape each plugin's *.js file for the human friendly name and help
 * text URL of each plugin.
 *
 * @return
 *   An array for each plugin.
 */
function _tinymce_get_buttons($skip_metadata = TRUE) {
  include_once drupal_get_path('module', 'tinymce') . '/plugin_reg.php';
  $plugins = _tinymce_plugins();
  if ($skip_metadata == FALSE && is_array($plugins)) {
    foreach ($plugins as $name => $plugin) {
      $file = drupal_get_path('module', 'tinymce') . '/tinymce/jscripts/tiny_mce/plugins/' . $name . '/editor_plugin_src.js';

      // Grab the plugin metadata by scanning the *.js file.
      if (file_exists($file)) {
        $lines = file($file);
        $has_longname = FALSE;
        $has_infourl = FALSE;
        foreach ($lines as $line) {
          if ($has_longname && $has_infourl) {
            break;
          }
          if (strstr($line, 'longname')) {
            $start = strpos($line, "'") + 1;
            $end = strrpos($line, "'") - $start;
            $metadata[$name]['longname'] = substr($line, $start, $end);
            $has_longname = TRUE;
          }
          elseif (strstr($line, 'infourl')) {
            $start = strpos($line, "'") + 1;
            $end = strrpos($line, "'") - $start;
            $metadata[$name]['infourl'] = substr($line, $start, $end);
            $has_infourl = TRUE;
          }
        }
      }

      // Find out the buttons a plugin has.
      foreach ($plugin as $k => $v) {
        if (strstr($k, 'theme_advanced_buttons')) {
          if (!isset($metadata[$name]['buttons'])) {
            $metadata[$name]['buttons'] = $plugin[$k];
          }
          else {
            $metadata[$name]['buttons'] = array_merge((array) $metadata[$name]['button'], $plugin[$k]);
          }
        }
      }

      // add list of default buttons
      // source: http://wiki.moxiecode.com/index.php/TinyMCE:Control_reference
      $name = 'default';
      $buttons = array(
        "bold",
        "italic",
        "underline",
        "strikethrough",
        "justifyleft",
        "justifycenter",
        "justifyright",
        "justifyfull",
        "bullist",
        "numlist",
        "outdent",
        "indent",
        "link",
        "unlink",
        "image",
        "cleanup",
        "help",
        "code",
        "hr",
        "removeformat",
        "sub",
        "sup",
        "charmap",
        "visualaid",
        "anchor",
        "blockquote",
      );
      foreach ($buttons as $button) {
        $metadata['default']['buttons'][] = $button;
      }
    }
    return $metadata;
  }
  return $plugins;
}

/********************************************************************
 * Module Functions :: Public
 ********************************************************************/

/**
 * Return an array of initial tinymce config options from the current role.
 */
function tinymce_config($profile) {
  global $user;

  // Drupal theme path.
  $themepath = path_to_theme() . '/';
  $host = base_path();
  $settings = $profile->settings;

  // Build a default list of TinyMCE settings.
  // Is tinymce on by default?
  $status = tinymce_user_get_status($user, $profile);
  $init['mode'] = $status == 'true' ? 'exact' : 'none';

  //  $init['mode']               = "textareas";
  $init['theme'] = $settings['theme'] ? $settings['theme'] : 'advanced';
  $init['relative_urls'] = 'false';
  $init['document_base_url'] = "{$host}";
  $init['language'] = $settings['language'] ? $settings['language'] : 'en';
  $init['safari_warning'] = $settings['safari_message'] ? $settings['safari_message'] : 'false';
  $init['entity_encoding'] = 'raw';
  $init['verify_html'] = $settings['verify_html'] ? $settings['verify_html'] : 'false';
  $init['preformatted'] = $settings['preformatted'] ? $settings['preformatted'] : 'false';
  $init['convert_fonts_to_spans'] = $settings['convert_fonts_to_spans'] ? $settings['convert_fonts_to_spans'] : 'false';
  $init['remove_linebreaks'] = $settings['remove_linebreaks'] ? $settings['remove_linebreaks'] : 'true';
  $init['apply_source_formatting'] = $settings['apply_source_formatting'] ? $settings['apply_source_formatting'] : 'true';
  $init['theme_advanced_resize_horizontal'] = 'false';
  $init['theme_advanced_resizing_use_cookie'] = 'false';
  $tinymce_mod_path = drupal_get_path('module', 'tinymce');
  if (is_dir($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/imagemanager/') && user_access('access tinymce imagemanager')) {

    // we probably need more security than this
    $init['file_browser_callback'] = "mcImageManager.filebrowserCallBack";
  }
  if (is_dir($tinymce_mod_path . '/tinymce/jscripts/tiny_mce/plugins/filemanager/') && user_access('access tinymce filemanager')) {

    // we probably need more security than this
    $init['file_browser_callback'] = "mcImageManager.filebrowserCallBack";
  }

  // Add support for IMCE if available.
  if (module_exists('imce') && imce_access()) {
    $init['file_browser_callback'] = 'mceImageBrowser';
  }
  if ($init['theme'] == 'advanced') {
    $init['plugins'] = array();
    $init['theme_advanced_toolbar_location'] = $settings['toolbar_loc'] ? $settings['toolbar_loc'] : 'bottom';
    $init['theme_advanced_toolbar_align'] = $settings['toolbar_align'] ? $settings['toolbar_align'] : 'left';
    $init['theme_advanced_path_location'] = $settings['path_loc'] ? $settings['path_loc'] : 'bottom';
    $init['theme_advanced_resizing'] = $settings['resizing'] ? $settings['resizing'] : 'true';
    $init['theme_advanced_blockformats'] = $settings['block_formats'] ? $settings['block_formats'] : 'p,address,pre,h1,h2,h3,h4,h5,h6';
    if (is_array($settings['buttons'])) {

      // This gives us the $plugins variable.
      $plugins = _tinymce_get_buttons();

      // Find the enabled buttons and the mce row they belong on. Also map the
      // plugin metadata for each button.
      $plugin_tracker = array();
      foreach ($plugins as $rname => $rplugin) {

        // Plugin name
        foreach ($rplugin as $mce_key => $mce_value) {

          // TinyMCE key
          foreach ($mce_value as $k => $v) {

            // Buttons
            if (isset($settings['buttons'][$rname . '-' . $v])) {

              // Font isn't a true plugin, rather it's buttons made available by the advanced theme
              if (!in_array($rname, $plugin_tracker) && $rname != 'font') {
                $plugin_tracker[] = $rname;
              }
              $init[$mce_key][] = $v;
            }
          }
        }

        // Some advanced plugins only have an $rname and no buttons
        if (isset($settings['buttons'][$rname])) {
          if (!in_array($rname, $plugin_tracker)) {
            $plugin_tracker[] = $rname;
          }
        }
      }

      // Add the rest of the TinyMCE config options to the $init array for each button.
      if (is_array($plugin_tracker)) {
        foreach ($plugin_tracker as $pname) {
          if ($pname != 'default') {
            $init['plugins'][] = $pname;
          }
          foreach ($plugins[$pname] as $mce_key => $mce_value) {

            // Don't overwrite buttons or extended_valid_elements
            if ($mce_key == 'extended_valid_elements') {

              // $mce_value is an array for extended_valid_elements so just grab the first element in the array (never more than one)
              $init[$mce_key][] = $mce_value[0];
            }
            elseif (!strstr($mce_key, 'theme_advanced_buttons')) {
              $init[$mce_key] = $mce_value;
            }
          }
        }
      }

      // Cleanup
      foreach ($init as $mce_key => $mce_value) {
        if (is_array($mce_value)) {
          $mce_value = array_unique($mce_value);
        }
        $init[$mce_key] = $mce_value;
      }

      // Shuffle buttons around so that row 1 always has the most buttons,
      // followed by row 2, etc. Note: These rows need to be set to NULL otherwise
      // TinyMCE loads it's own buttons inherited from the theme.
      if (!isset($init['theme_advanced_buttons1'])) {
        $init['theme_advanced_buttons1'] = array();
      }
      if (!isset($init['theme_advanced_buttons2'])) {
        $init['theme_advanced_buttons2'] = array();
      }
      if (!isset($init['theme_advanced_buttons3'])) {
        $init['theme_advanced_buttons3'] = array();
      }

      // bweh - this isn't right!
      // some buttons should go in a specific order:
      // row 1
      // - cut
      // - copy
      // - paste
      // - pasteword
      // - separator
      // - undo
      // - redo
      // - separator
      // - bold
      // - italic
      // - underline
      // - separator
      // row 2
      // - formatselect
      // - fontselect
      // - fontsizeselect
      // - separator
      // - justifyleft
      // - justifycenter
      // - justifyright
      // - justifyfull
      // - separator
      // - numlist
      // - bullist
      // - indent
      // - outdent
      $buttons = array_merge($init['theme_advanced_buttons1'], $init['theme_advanced_buttons2'], $init['theme_advanced_buttons3']);
      $init['theme_advanced_buttons1'] = array();
      $init['theme_advanced_buttons2'] = array();
      $init['theme_advanced_buttons3'] = array();
      $row[] = array(
        array(
          'newdocument',
          'save',
        ),
        array(
          'bold',
          'italic',
          'underline',
        ),
        array(
          'undo',
          'redo',
        ),
        array(
          'cut',
          'copy',
          'paste',
          'pasteword',
        ),
        array(
          'link',
          'unlink',
        ),
        array(
          'image',
          'charmap',
        ),
        array(
          'code',
        ),
      );
      $row[] = array(
        array(
          'formatselect',
          'fontselect',
          'fontsizeselect',
        ),
        array(
          'justifyleft',
          'justifycenter',
          'justifyright',
          'justifyfull',
        ),
        array(
          'numlist',
          'bullist',
          'indent',
          'outdent',
        ),
      );
      foreach ($row as $r_index => $r) {
        $row_buttons = array();
        foreach ($r as $rg_index => $rowgroup) {
          $selected = array_intersect($rowgroup, $buttons);
          if (count($selected) > 0) {
            if (count($row_buttons) > 0) {
              $row_buttons[] = "separator";
            }
            $row_buttons = array_merge($row_buttons, $selected);
          }
          $buttons = array_diff($buttons, $selected);
        }
        $init['theme_advanced_buttons' . ($r_index + 1)] = $row_buttons;
      }
      if (count($buttons) > 0) {

        // some buttons are left -> append them to row 3
        $init['theme_advanced_buttons3'] = array_merge($init['theme_advanced_buttons3'], $buttons);
      }
      $min_btns = 5;

      // Minimum number of buttons per row.
      $num1 = count($init['theme_advanced_buttons1']);
      $num2 = count($init['theme_advanced_buttons2']);
      $num3 = count($init['theme_advanced_buttons3']);
      if ($num3 < $min_btns) {
        $init['theme_advanced_buttons2'][] = 'separator';
        $init['theme_advanced_buttons2'] = array_merge($init['theme_advanced_buttons2'], $init['theme_advanced_buttons3']);
        $init['theme_advanced_buttons3'] = array();
        $num2 = count($init['theme_advanced_buttons2']);
      }
      if ($num2 < $min_btns) {
        $init['theme_advanced_buttons1'][] = 'separator';
        $init['theme_advanced_buttons1'] = array_merge($init['theme_advanced_buttons1'], $init['theme_advanced_buttons2']);

        // Squish the rows together, since row 2 is empty
        $init['theme_advanced_buttons2'] = $init['theme_advanced_buttons3'];
        $init['theme_advanced_buttons3'] = array();
        $num1 = count($init['theme_advanced_buttons1']);
      }
      if ($num1 < $min_btns) {
        $init['theme_advanced_buttons1'] = array_merge($init['theme_advanced_buttons1'], $init['theme_advanced_buttons2']);

        // Squish the rows together, since row 2 is empty
        $init['theme_advanced_buttons2'] = $init['theme_advanced_buttons3'];
        $init['theme_advanced_buttons3'] = array();
      }
    }
  }
  if ($settings['css_classes']) {
    $init['theme_advanced_styles'] = $settings['css_classes'];
  }
  if ($settings['css_setting'] == 'theme') {
    $css = $themepath . 'style.css';
    if (file_exists($css)) {
      $init['content_css'] = $host . $css;
    }
  }
  elseif ($settings['css_setting'] == 'self') {
    $init['content_css'] = str_replace(array(
      '%h',
      '%t',
    ), array(
      $host,
      $themepath,
    ), $settings['css_path']);
  }
  return $init;
}

/**
 * Load all profiles. Just load one profile if $name is passed in.
 */
function tinymce_profile_load($name = '') {
  static $profiles = array();
  if (!$profiles) {
    $roles = user_roles();
    $result = db_query('SELECT * FROM {tinymce_settings}');
    while ($data = db_fetch_object($result)) {
      $data->settings = unserialize($data->settings);
      $result2 = db_query("SELECT rid FROM {tinymce_role} WHERE name = '%s'", $data->name);
      $role = array();
      while ($r = db_fetch_object($result2)) {
        $role[$r->rid] = $roles[$r->rid];
      }
      $data->rids = $role;
      $profiles[$data->name] = $data;
    }
  }
  return $name ? $profiles[$name] : $profiles;
}

/********************************************************************
 * Module Functions :: Private
 ********************************************************************/

/**
 * Determine if TinyMCE has permission to be used on the current page.
 *
 * @return
 *   TRUE if can render, FALSE if not allowed.
 */
function _tinymce_page_match($edit) {
  $page_match = FALSE;
  if (is_numeric(arg(1)) && arg(2) == 'edit') {
    $node = node_load(arg(1));
    $result = db_query("SELECT format FROM {filters} WHERE module = 'php'");
    while ($data = db_fetch_object($result)) {
      if ($node->format == $data->format) {
        return FALSE;
      }
    }
  }
  if ($edit->settings['access_pages']) {

    // If the PHP option wasn't selected
    if ($edit->settings['access'] < 2) {
      $path = drupal_get_path_alias($_GET['q']);
      $regexp = '/^(' . preg_replace(array(
        '/(\\r\\n?|\\n)/',
        '/\\\\\\*/',
        '/(^|\\|)\\\\<front\\\\>($|\\|)/',
      ), array(
        '|',
        '.*',
        '\\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\\2',
      ), preg_quote($edit->settings['access_pages'], '/')) . ')$/';
      $page_match = !($edit->settings['access'] xor preg_match($regexp, $path));
    }
    else {
      $page_match = drupal_eval($edit->settings['access_pages']);
    }
  }
  else {
    $page_match = TRUE;
  }
  return $page_match;
}
function tinymce_user_get_profile($account) {
  $profile_name = db_result(db_query('SELECT s.name FROM {tinymce_settings} s INNER JOIN {tinymce_role} r ON r.name = s.name WHERE r.rid IN (%s)', implode(',', array_keys($account->roles))));
  if ($profile_name) {
    return tinymce_profile_load($profile_name);
  }
  else {
    return FALSE;
  }
}
function tinymce_user_get_status($user, $profile) {
  $settings = $profile->settings;
  if ($settings['user_choose']) {
    $status = isset($user->tinymce_status) ? $user->tinymce_status : (isset($settings['default']) ? $settings['default'] : 'false');
  }
  else {
    $status = isset($settings['default']) ? $settings['default'] : 'false';
  }
  return $status;
}

Functions

Namesort descending Description
theme_tinymce_theme Customize a TinyMCE theme.
tinymce_config Return an array of initial tinymce config options from the current role.
tinymce_elements Implementation of hook_elements().
tinymce_form_alter Implementation of hook_form_alter()
tinymce_help Implementation of hook_help().
tinymce_menu Implementation of hook_menu().
tinymce_perm Implementation of hook_perm().
tinymce_process_textarea Attach tinymce to a textarea
tinymce_profile_load Load all profiles. Just load one profile if $name is passed in.
tinymce_theme Implementation of hook_theme()
tinymce_user Implementation of hook_user().
tinymce_user_get_profile
tinymce_user_get_status
_tinymce_get_buttons Return plugin metadata from the plugin registry.
_tinymce_get_themes Grab the themes available to TinyMCE.
_tinymce_page_match Determine if TinyMCE has permission to be used on the current page.