[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/ckeditor/includes/ -> ckeditor.admin.inc (source)

   1  <?php
   2  /**
   3   * CKEditor - The text editor for the Internet - http://ckeditor.com
   4   * Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
   5   *
   6   * == BEGIN LICENSE ==
   7   *
   8   * Licensed under the terms of any of the following licenses of your
   9   * choice:
  10   *
  11   *  - GNU General Public License Version 2 or later (the "GPL")
  12   *    http://www.gnu.org/licenses/gpl.html
  13   *
  14   *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
  15   *    http://www.gnu.org/licenses/lgpl.html
  16   *
  17   *  - Mozilla Public License Version 1.1 or later (the "MPL")
  18   *    http://www.mozilla.org/MPL/MPL-1.1.html
  19   *
  20   * == END LICENSE ==
  21   *
  22   * @file
  23   * CKEditor Module for Drupal 6.x
  24   *
  25   * This module allows Drupal to replace textarea fields with CKEditor.
  26   *
  27   * CKEditor is an online rich text editor that can be embedded inside web pages.
  28   * It is a WYSIWYG (What You See Is What You Get) editor which means that the
  29   * text edited in it looks as similar as possible to the results end users will
  30   * see after the document gets published. It brings to the Web popular editing
  31   * features found in desktop word processors such as Microsoft Word and
  32   * OpenOffice.org Writer. CKEditor is truly lightweight and does not require any
  33   * kind of installation on the client computer.
  34   */
  35  
  36  /**
  37   * Main administrative page
  38   */
  39  function ckeditor_admin_main() {
  40    module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
  41    $editor_path = ckeditor_path(TRUE);
  42    $ckconfig_file = $editor_path .'/config.js';
  43    if (!_ckeditor_requirements_isinstalled()) {
  44      drupal_set_message(t(
  45        'Checking for !filename or !file.',
  46        array(
  47          '!filename' => '<code>' . $ckconfig_file . '</code>',
  48          '!file' => '<code>sites/all/libraries/ckeditor/ckeditor.js</code>'
  49        )
  50      ));
  51      drupal_set_message(t(
  52        'The CKEditor component is not installed correctly. Please go to the !ckeditorlink in order to download the latest version. After that you must extract the files to the !ckeditorpath or !librarypath directory and make sure that the !ckeditorfile or !ckeditorlibrary file exists. Refer to the !readme file for more information.',
  53        array(
  54          '!ckeditorlink' => l(t('CKEditor homepage'), 'http://ckeditor.com/download'),
  55          '!readme' => l(t('README.txt'), drupal_get_path('module', 'ckeditor') . '/README.txt', array('absolute' => TRUE)),
  56          '!ckeditorpath' => '<code>' . $editor_path . '</code>',
  57          '!ckeditorsubdir' => '<code>' . $editor_path . '/editor</code>',
  58          '!ckeditorfile' => '<code>' . $editor_path . '/ckeditor.js</code>',
  59          '!ckeditorlibrary' => '<code>sites/all/libraries/ckeditor/ckeditor.js</code>',
  60          '!librarypath' => '<code>sites/all/libraries/ckeditor</code>'
  61        )
  62      ), 'error');
  63      drupal_set_message(t(
  64        'If you have CKEditor already installed, edit the <strong>!editg</strong> and update the CKEditor path.',
  65        array(
  66          '!editg' => l(t('CKEditor Global Profile'), 'admin/settings/ckeditor/editg')
  67        )
  68      ), 'warning');
  69      return FALSE;
  70    }
  71  
  72    if (module_exists('wysiwyg')) {
  73      drupal_set_message(t(
  74        'The WYSIWYG module was detected. Using both modules at the same time may cause problems. It is recommended to turn the WYSIWYG module off (!wysiwygdisablelink").',
  75        array(
  76          '!wysiwygdisablelink' => l(t('click here to disable'), 'ckeditor/disable/wysiwyg/' . drupal_get_token('ckeditorDisableWysiwyg'))
  77        )
  78      ), 'warning');
  79    }
  80  
  81    $access_ckeditor_roles = user_roles(FALSE, 'access ckeditor');
  82    if (!$access_ckeditor_roles) {
  83      drupal_set_message(t(
  84        'There is currently no role with the "access ckeditor" permission. Visit the !acl administration section.',
  85        array(
  86          '!acl' => l(t('Permissions'), 'admin/user/permissions')
  87        )
  88      ), 'warning');
  89    }
  90    else {
  91      $result = db_query_range("SELECT name FROM {ckeditor_settings} WHERE name<>'CKEditor Global Profile'", 0, 1);
  92      $has_profiles = FALSE;
  93      //find profile other than Global
  94      if (($obj = db_fetch_object($result))) {
  95        $has_profiles = TRUE;
  96      }
  97  
  98      //find roles with profiles
  99      $result = db_query("SELECT rid FROM {ckeditor_role}");
 100      $rids = array();
 101      while (($obj = db_fetch_object($result))) {
 102          $rids[] = $obj->rid;
 103      }
 104      $rids = array_unique($rids);
 105      if (!$has_profiles) {
 106        drupal_set_message(t('No CKEditor profiles found. Right now nobody is able to use CKEditor. Create a new profile below.'), 'error');
 107      }
 108      else {
 109        //not all roles with access ckeditor has their CKEditor profile assigned
 110        $diff = array_diff(array_keys($access_ckeditor_roles), $rids);
 111        if ($diff) {
 112          $list = "<ul>";
 113          foreach ($diff as $rid) {
 114            $list .= "<li>". $access_ckeditor_roles[$rid] ."</li>";
 115          }
 116          $list .= "</ul>";
 117          drupal_set_message(t(
 118            'Not all roles with the "!access" permission are associated with CKEditor profiles. As a result, users with the following roles may be unable to use CKEditor: !list Create new or edit existing CKEditor profiles below and check the "Roles allowed to use this profile" option in the <strong>Basic setup</strong> section.',
 119            array(
 120              '!access' => l(t('access ckeditor'), 'admin/user/permissions'),
 121              '!list' => $list
 122            )
 123          ), 'warning');
 124        }
 125      }
 126    }
 127  
 128    return ckeditor_profile_overview();
 129  }
 130  
 131  /**
 132   * Controller for CKEditor profiles.
 133   */
 134  function ckeditor_profile_overview() {
 135    $output = '';
 136  
 137    $profiles = ckeditor_profile_load();
 138    if ($profiles) {
 139      $access_ckeditor_roles = user_roles(FALSE, 'access ckeditor');
 140      $header = array(t('Profile'), t('Roles'), t('Operations'));
 141      foreach ($profiles as $p) {
 142        $rids = $p->rids;
 143        if ($p->name !== "CKEditor Global Profile") {
 144          foreach (array_keys($p->rids) as $rid) {
 145            if (!isset($access_ckeditor_roles[$rid])) {
 146              unset($rids[$rid]);
 147            }
 148          }
 149          $rows[] = array(
 150            array('data' => $p->name, 'valign' => 'top'),
 151            array('data' => implode("<br />\n", $rids)),
 152            array(
 153              'data' =>
 154                l(t('edit'), 'admin/settings/ckeditor/edit/'. urlencode($p->name)) .' '.
 155                l(t('clone'), 'admin/settings/ckeditor/clone/'. urlencode($p->name)) .' '.
 156                l(t('delete'), 'admin/settings/ckeditor/delete/'. urlencode($p->name)),
 157              'valign' => 'top'
 158            )
 159          );
 160        }
 161      }
 162      $output .= '<h3>' . t('Profiles') .'</h3>';
 163      $output .= theme('table', $header, $rows);
 164      $output .= '<p>' . l(t('Create a new profile'), 'admin/settings/ckeditor/add') . '</p>';
 165    }
 166    else {
 167      drupal_set_message(t(
 168        'No profiles found. Click here to !create.',
 169        array(
 170          '!create' => l(t('create a new profile'), 'admin/settings/ckeditor/add')
 171        )
 172      ));
 173    }
 174  
 175    $rows = array();
 176    if (!isset($profiles['CKEditor Global Profile'])) {
 177      drupal_set_message(t(
 178        'The global profile can not be found. Click here to !create.',
 179        array(
 180          '!create' => l(t('create the global profile'), 'admin/settings/ckeditor/addg')
 181        )
 182      ));
 183    }
 184    else {
 185      $output .= "<h3>" . t("Global settings") ."</h3>";
 186      $rows[] = array(
 187        array('data' => t('CKEditor Global Profile'), 'valign' => 'top'),
 188        array(
 189          'data' =>
 190            l(t('edit'), 'admin/settings/ckeditor/editg') . " " .
 191            l(t('delete'), 'admin/settings/ckeditor/delete/CKEditor Global Profile'),
 192          'valign' => 'top'
 193        )
 194      );
 195      $output .= theme('table', array(t('Profile'), t('Operations')), $rows);
 196    }
 197    return $output;
 198  }
 199  
 200  /**
 201   * Clone profile
 202   */
 203  function ckeditor_admin_profile_clone_form($form_state, $oldprofile) {
 204    return ckeditor_admin_profile_form($form_state, $oldprofile);
 205  }
 206  
 207  function ckeditor_admin_profile_clone_form_validate($form_state, $oldprofile) {
 208    ckeditor_admin_profile_form_validate($form_state, $oldprofile);
 209  }
 210  
 211  function ckeditor_admin_profile_clone_form_submit($form, &$form_state) {
 212    $edit =& $form_state['values'];
 213    drupal_set_message(t('Your CKEditor profile was created.'));
 214    $settings = ckeditor_admin_values_to_settings($edit);
 215    db_query("INSERT INTO {ckeditor_settings} (name, settings) VALUES ('%s', '%s')", $edit['name'], $settings);
 216    ckeditor_rebuild_selectors($edit['name']);
 217    if (!empty($edit['rids'])) {
 218      foreach (array_keys($edit['rids']) as $rid) {
 219        if ($edit['rids'][$rid]!=0) {
 220          db_query("INSERT INTO {ckeditor_role} (name, rid) VALUES ('%s', %d)", $edit['name'], $rid);
 221        }
 222      }
 223    }
 224    $form_state['redirect'] = 'admin/settings/ckeditor';
 225  }
 226  
 227  /**
 228   * Form builder for a normal profile
 229   */
 230  function ckeditor_admin_profile_form($form_state, $profile = NULL) {
 231    global $theme;
 232    if ($profile != NULL) {
 233      $form['_profile'] = array(
 234        '#type' => 'value',
 235        '#value' => $profile,
 236      );
 237    }
 238    else {
 239      $profile = new stdClass();
 240    }
 241  
 242    module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
 243  
 244    $skin_options = ckeditor_load_skin_options();
 245    $lang_options = ckeditor_load_lang_options();
 246  
 247    // Only display the roles that currently don't have a ckeditor profile. One
 248    // profile per role.
 249    $orig_roles = user_roles(FALSE, 'access ckeditor');
 250    $roles = $orig_roles;
 251  
 252    if (!empty($profile->rids) && !user_roles(FALSE, 'access ckeditor')) {
 253      drupal_set_message(t(
 254        'You have not assigned the "access ckeditor" !permissions yet. It is recommended to assign the "access ckeditor" !permissions before updating CKEditor profiles.',
 255        array(
 256          '!permissions' => l(t('permissions'), 'admin/user/permissions')
 257        )
 258      ), 'warning');
 259    }
 260  
 261    if (empty($profile->name)) {
 262      $result = db_query("SELECT DISTINCT(rid) FROM {ckeditor_role}");
 263      while (($data = db_fetch_object($result))) {
 264        if ((empty($profile->rids) || !in_array($data->rid, array_keys((array) $profile->rids))) && !form_get_errors()) {
 265          unset($roles[$data->rid]);
 266        }
 267      }
 268      if (count($orig_roles) != count($roles)) {
 269        drupal_set_message(t('Not all user roles are shown since they already have CKEditor profiles assigned. You must first remove the assignment of profiles in order to add them to a new one.'));
 270      }
 271    }
 272  
 273    $form['basic'] = array(
 274      '#type' => 'fieldset',
 275      '#title' => t('Basic setup'),
 276      '#collapsible' => TRUE,
 277      '#collapsed' => TRUE
 278    );
 279  
 280  
 281    switch (arg(3)) {
 282      case 'clone':
 283        //load all profiles to check their names
 284        $profiles = ckeditor_profile_load();
 285        $oldname = $profile->name;
 286        $maxsize=128;   //default max name length
 287  
 288        $res=array();
 289        $pat = "/^(.*?)_([0-9]+)$/";
 290        if (preg_match($pat, $oldname, $res)) {     // oldname like 'name_nr'
 291          $name=$res[1];
 292          $num=$res[2]+1;
 293        }
 294        else{
 295          $name=$oldname;
 296          $num=2;
 297        }
 298  
 299        $newname=substr($name, 0, $maxsize-3) .'_'. $num;   // +limit
 300        while (isset($profiles[$newname])) {            //find next free number
 301          $num++;
 302          $newname=substr($name, 0, $maxsize-3) .'_'. $num;
 303        }
 304        //dont clone rids
 305        $profile->settings['rids']=array();
 306        $profile->rids=array();
 307        break;
 308      case 'edit':
 309        $newname = $profile->name;
 310        break;
 311    }
 312  
 313    $global_profile = ckeditor_profile_load("CKEditor Global Profile");
 314    $toolbar_wizard = !empty($global_profile->settings['toolbar_wizard']) ? $global_profile->settings['toolbar_wizard'] : 't';
 315    drupal_add_js(array('ckeditor_toolbar_wizard' => $toolbar_wizard), 'setting');
 316  
 317    $form['basic']['name'] = array(
 318      '#type' => 'textfield',
 319      '#title' => t('Profile name'),
 320      '#default_value' => !empty($profile->name) ? $newname : '',
 321      '#size' => 40,
 322      '#maxlength' => 128,
 323      '#description' => t('Enter a name for this profile. This name is only visible within the CKEditor administration page.'),
 324      '#required' => TRUE
 325    );
 326  
 327    $form['basic']['rids'] = array(
 328      '#type' => 'checkboxes',
 329      '#title' => t('Roles allowed to use this profile'),
 330      '#default_value' => !empty($profile->rids) ? array_keys((array) $profile->rids) : array(),
 331      '#options' => $roles,
 332      '#description' =>  t(
 333        'Only roles with the "access ckeditor" permission will be shown here. If no role is available, make sure that you have assigned the "access ckeditor" <a href="!permission">permission</a>.',
 334        array(
 335          '!permission' => l(t('permission'), 'admin/user/permissions')
 336        )
 337      ),
 338      '#required' => TRUE
 339    );
 340  
 341    $form['basic']['allow_user_conf'] = array(
 342      '#type' => 'radios',
 343      '#title' => t('Allow users to customize CKEditor appearance'),
 344      '#default_value' => !empty($profile->settings['allow_user_conf']) ? $profile->settings['allow_user_conf'] : 'f',
 345      '#options' => array(
 346        'f' => t('No'),
 347        't' => t('Yes')
 348      ),
 349      '#description' => t('If allowed, users will be able to override the "Editor appearance" by visiting their profile page.'),
 350    );
 351  
 352    $form['security'] = array(
 353      '#type' => 'fieldset',
 354      '#title' => t('Security'),
 355      '#description' => '<p>'. t('The CKEditor security system protects you from executing malicious code that is already in your database. In plain textareas database content is harmless because it is not executed, but the CKEditor WYSIWYG editor interprets HTML like a web browser and thus the content needs to be filtered before it is loaded.') .'</p>',
 356      '#collapsible' => TRUE,
 357      '#collapsed' => TRUE
 358    );
 359  
 360    $all = filter_list_all();
 361  
 362    $form['security']['filters'] = array(
 363      '#type' => 'fieldset',
 364      '#title' => t('Security filters'),
 365      '#description' => t('Please choose all filters that protect your content (probably not all filters listed below are security filters).'),
 366      '#tree' => TRUE,
 367    );
 368  
 369    //don't bother administrator with filters that definitely are not security filters
 370    $modules_with_filters_to_skip = array('amazon_filter', 'asy', 'bbcode', 'biblio', 'blockquote', 'bookpost', 'chessboard', 'citation_filter', 'codefilter', 'collapse_text', 'contextlinks', 'coolfilter', 'dialectic', 'dript', 'dme', 'drutex', 'embedfilter', 'ext_link_page', 'extlink', 'elf', 'flickr', 'flickrstickr', 'footnotes', 'formdefaults', 'freelinking', 'gallery', 'geogebra', 'geshifilter', 'gotwo', 'googtube', 'gotcha', 'gtspam', 'hidden_content', 'img_assist', 'image_filter', 'imagebrowser', 'inlinetags', 'insert_view', 'insertframe', 'insertnode', 'interwiki', 'jlightbox', 'jsmath', 'language_sections', 'link_node', 'lootz', 'markdown', 'marksmarty', 'mobile_codes', 'mykml', 'nofollowlist', 'oagwt', 'paging', 'pathfilter', 'pearwiki_filter', 'php', 'pirate', 'reptag', 'scrippet', 'scripturefilter', 'signwriter', 'slideshowpro', 'smartlinebreakconverter', 'smartypants', 'smileys', 'spamspan', 'spam_tokens', 'spoiler', 'table_altrow', 'tablemanager', 'tableofcontents', 'textile', 'tooltips', 'twikifilter', 'typogrify', 'unwrap', 'urlclass', 'urlicon', 'url_replace_filter', 'username_highlighter', 'video_filter', 'quote');
 371  
 372    if (!isset($profile->settings['ss'])) {
 373      $profile->settings['filters']['filter/0'] = 1;
 374    }
 375  
 376    foreach ($all as $id => $filter) {
 377      if (in_array(strtolower($filter->module), $modules_with_filters_to_skip)) {
 378        continue;
 379      }
 380      //skip line break converter and email -> link
 381      if ($filter->module == 'filter' && in_array($filter->delta, array(1, 2))) {
 382        continue;
 383      }
 384      $form['security']['filters'][$id] = array(
 385        '#type' => 'checkbox',
 386        '#title' => check_plain($filter->name),
 387        '#default_value' => !empty($profile->settings['filters'][$id]),
 388        '#description' => check_plain(module_invoke($filter->module, 'filter', 'description', $filter->delta)),
 389      );
 390    }
 391  
 392    $form['security']['ss'] = array(
 393      '#type' => 'radios',
 394      '#title' => t('Security settings'),
 395      '#default_value' => isset($profile->settings['ss']) ? $profile->settings['ss'] : '2',
 396      '#options' => array(
 397        '2' => t('Always run security filters for CKEditor.'),
 398        '1' => t('Run security filters only when CKEditor is set to start automatically.'),
 399      ),
 400      '#description' => t('There are two ways of starting CKEditor: automatically and manually (via toggle or in a popup). If you decide to apply security filters only when CKEditor starts automatically, you will not be protected when toggling manually from plain textarea to CKEditor or when using CKEditor in the popup mode. Choose this option only if you can detect various attacks (mainly XSS) by yourself just by looking at the HTML code.'),
 401    );
 402  
 403    $form['ckeditor_exclude_settings'] = array(
 404      '#type' => 'fieldset',
 405      '#title' => t('Visibility settings'),
 406      '#collapsible' => TRUE,
 407      '#collapsed' => TRUE,
 408      '#description' => t('The following settings are combined with the visibility settings of the global profile.'),
 409    );
 410  
 411    $form['ckeditor_exclude_settings']['min_rows'] = array(
 412      '#type' => 'textfield',
 413      '#title' => t('Minimum rows'),
 414      '#default_value' => !empty($profile->settings['min_rows']) ? $profile->settings['min_rows'] : '1',
 415      '#description' => t("CKEditor will be triggered if the textarea has more rows than the number given here. Enter '1' if you do not want to use this feature."),
 416    );
 417  
 418    $form['ckeditor_exclude_settings']['excl_mode'] = array(
 419      '#type' => 'radios',
 420      '#title' => t('Use inclusion or exclusion mode'),
 421      '#default_value' => (empty($profile->settings['excl_mode']) || in_array($profile->settings['excl_mode'], array(0, 2))) ? 0 : 1,
 422      '#options' => array(
 423        '0' => t('Exclude'),
 424        '1' => t('Include')
 425      ),
 426      '#description' => t('Choose the way of disabling/enabling CKEditor on selected fields/paths (see below). Use <strong>Exclude</strong> to disable CKEditor on selected fields/paths. Use <strong>Include</strong> if you want to load CKEditor only on selected paths/fields.'),
 427    );
 428  
 429    /**
 430     * get excluded fields - so we can have normal textareas too
 431     * split the phrase by any number of commas or space characters,
 432     * which include " ", \r, \t, \n and \f
 433     */
 434    $form['ckeditor_exclude_settings']['excl'] = array(
 435      '#type' => 'textarea',
 436      '#title' => t('Fields to exclude/include'),
 437      '#cols' => 60,
 438      '#rows' => 5,
 439      '#prefix' => '<div style="margin-left:20px">',
 440      '#suffix' => '</div>',
 441      '#default_value' => !empty($profile->settings['excl']) ? $profile->settings['excl'] : '',
 442      '#description' => t('Enter the paths to the textarea fields for which you want to enable or disable CKEditor.') .
 443        ' ' .
 444        t('See the !helppagelink for more information about defining field names. Short instruction is available below.',
 445          array(
 446            '!helppagelink' => l(t('Help page'), 'admin/help/ckeditor', array('fragment' => 'fieldinclexcl'))
 447          )
 448        ) .
 449        ' <ul><li>' .
 450        t('Path structure: <strong>theme_name:content_type@path.element_id</strong>') .
 451        '</li><li>' .
 452        t('The following wildcards are available: "*", "?".') .
 453        '</li><li>' .
 454        t('Content type and theme name is optional. You may even just specify the path or the field ID.') .
 455        '</li><li>' .
 456        t('Examples:') .
 457        '<ul><li><em>garland:blog@*.edit-body</em> - ' .
 458        t('matches all fields of type <code>blog</code> called <code>edit-body</code> in the garland theme, on any page.') .
 459        '<li><em>node/add/*.edit-user-*</em> - ' .
 460        t('matches fields starting with <code>edit-user-</code> on pages starting with <code>node/add/</code>') .
 461        '</li></ul></li></ul>',
 462      '#wysiwyg' => FALSE,
 463    );
 464  
 465    $form['ckeditor_exclude_settings']['simple_incl'] = array(
 466      '#type' => 'textarea',
 467      '#title' => t('Force simplified toolbar on the following fields'),
 468      '#cols' => 60,
 469      '#rows' => 5,
 470      '#default_value' => !empty($profile->settings['simple_incl']) ? $profile->settings['simple_incl'] : '',
 471      '#description' => t('Enter the paths to the textarea fields for which you want to force the simplified toolbar.') .
 472        ' ' .
 473        t(
 474          'Please see the !helppagelink for more information about defining field names. Take a look at the exclusion settings (above) for a short instruction.',
 475          array(
 476            '!helppagelink' => l(t('Help page'), 'admin/help/ckeditor', array('fragment' => 'fieldinclexcl'))
 477          )
 478        ),
 479      '#wysiwyg' => FALSE,
 480    );
 481  
 482    $form['appearance'] = array(
 483      '#type' => 'fieldset',
 484      '#title' => t('Editor appearance'),
 485      '#collapsible' => TRUE,
 486      '#collapsed' => TRUE,
 487    );
 488  
 489    $form['appearance']['default'] = array(
 490      '#type' => 'radios',
 491      '#title' => t('Default state'),
 492      '#default_value' => !empty($profile->settings['default']) ? $profile->settings['default'] : 't',
 493      '#options' => array(
 494        't' => t('Enabled'),
 495        'f' => t('Disabled')
 496      ),
 497      '#description' => t('Default editor state. If disabled, the rich text editor may still be enabled by using toggle or popup window.'),
 498    );
 499  
 500    $form['appearance']['show_toggle'] = array(
 501      '#type' => 'radios',
 502      '#title' => t('Show the disable/enable rich text editor toggle'),
 503      '#default_value' => !empty($profile->settings['show_toggle']) ? $profile->settings['show_toggle'] : 't',
 504      '#options' => array(
 505        't' => t('Show'),
 506        'f' => t('Hide')
 507      ),
 508      '#description' => t('Whether or not to show the disable/enable rich text editor toggle below the textarea. Works only if CKEditor is not running in a popup window (see below).'),
 509    );
 510  
 511    $form['appearance']['popup'] = array(
 512      '#type' => 'radios',
 513      '#title' => t('Use CKEditor in a popup window'),
 514      '#default_value' => !empty($profile->settings['popup']) ? $profile->settings['popup'] : 'f',
 515      '#options' => array(
 516        'f' => t('No'),
 517        't' => t('Yes')
 518      ),
 519      '#description' => t('If this option is enabled, a link to a popup window will be used instead of a textarea replace.'),
 520    );
 521  
 522    $form['appearance']['skin'] = array(
 523      '#type' => 'select',
 524      '#title' => t('Skin'),
 525      '#default_value' => !empty($profile->settings['skin']) ? $profile->settings['skin'] : 'default',
 526      '#options' => $skin_options,
 527      '#description' => t('Choose a CKEditor skin.'),
 528    );
 529  
 530    $ui_colors = array(
 531      "default" => t('CKEditor default'),
 532      "custom" => t('Select manually')
 533    );
 534    if (function_exists('color_get_palette')) {
 535      // apparently $theme is not initialized (?)
 536      if (empty($theme)) {
 537        init_theme();
 538      }
 539      $palette = @color_get_palette($theme, FALSE); //[#652274]
 540      $color_palette['default'] = '#D3D3D3';
 541      if (!empty($palette)) {
 542        if (!empty($palette['base'])) {
 543          $color_palette['color_base'] = $palette['base'];
 544          $ui_colors["color_base"] = t('Color module: base');
 545        }
 546        if (!empty($palette['top'])) {
 547          $color_palette['color_top'] = $palette['top'];
 548          $ui_colors["color_top"] = t('Color module: top');
 549        }
 550        if (!empty($palette['bottom'])) {
 551          $color_palette['color_bottom'] = $palette['bottom'];
 552          $ui_colors["color_bottom"] = t('Color module: bottom');
 553        }
 554      }
 555      drupal_add_js(array('ckeditor_uicolor' => $color_palette), 'setting');
 556    }
 557  
 558    $editor_path = ckeditor_path(FALSE);
 559    $module_drupal_path = drupal_get_path('module', 'ckeditor');
 560  
 561    drupal_set_html_head('<script type="text/javascript">window.CKEDITOR_BASEPATH = "' . $editor_path . '/";</script>');
 562    drupal_set_html_head('<script type="text/javascript" src="'. $editor_path .'/ckeditor.js?I"></script>');
 563    drupal_add_js($module_drupal_path . '/ckeditor.config.js', 'file');
 564    drupal_add_js($module_drupal_path . '/includes/ckeditor.admin.js', 'file');
 565  
 566    if ($toolbar_wizard == 't') {
 567      if (module_exists('jquery_ui')) {
 568        if (!module_exists('jquery_update')  || jquery_update_get_version() <= 1.2 )
 569          drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-1.4.4.min.js', 'core');
 570          if (jquery_ui_get_version() > 1.6) {
 571            jquery_ui_add(array('ui.sortable'));
 572          }
 573          else {
 574            drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-ui.min.js', 'file');
 575            drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.widget.min.js', 'file');
 576            drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.sortable.min.js', 'file');
 577          }
 578      }
 579      else {
 580        if (!module_exists('jquery_update') || jquery_update_get_version() <= 1.2 )
 581          drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-1.4.4.min.js', 'core');
 582        drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-ui.min.js', 'file');
 583        drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.widget.min.js', 'file');
 584        drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.sortable.min.js', 'file');
 585      }
 586      drupal_add_js($module_drupal_path . '/includes/jqueryUI/sort.js', 'file');
 587    }
 588  
 589    $form['appearance']['uicolor'] = array(
 590      '#type' => 'select',
 591      '#title' => t('User interface color'),
 592      '#default_value' => !empty($profile->settings['uicolor']) ? $profile->settings['uicolor'] : 'default',
 593      '#options' => $ui_colors,
 594      '#description' => t(
 595        'Works only with the "!skin" skin.',
 596        array(
 597          '!skin' => 'Kama'
 598        )),
 599      );
 600    $form['appearance']['uicolor_textarea'] = array(
 601      '#type' => 'textarea',
 602      '#title' => '',
 603      '#default_value' => 'Click the <strong>UI Color Picker</strong> button to set your color preferences.',
 604      '#attributes' => array('style' => 'display:none', 'class' => 'ckeditor_ui_demo'),
 605      '#resizable' => FALSE,
 606      '#wysiwyg' => FALSE
 607    );
 608    $form['appearance']['uicolor_user'] = array(
 609      '#type' => 'hidden',
 610      '#default_value' => !empty($profile->settings['uicolor_user']) ? $profile->settings['uicolor_user'] : 'default',
 611    );
 612  
 613    $form['appearance']['toolbar'] = array(
 614      '#type' => 'textarea',
 615      '#title' => t('Toolbar'),
 616      '#default_value' => !empty($profile->settings['toolbar']) ? $profile->settings['toolbar'] : '',
 617      '#description' => t('Load sample toolbar: <a href="#" id="cke_toolbar_DrupalBasic" class="cke_load_toolbar">Basic</a> | <a href="#" id="cke_toolbar_DrupalAdvanced" class="cke_load_toolbar">Advanced</a> | <a href="#" id="cke_toolbar_DrupalFull" class="cke_load_toolbar">Full</a>'),
 618      '#wysiwyg' => FALSE,
 619      '#rows' => 15
 620    );
 621  
 622    if ($toolbar_wizard == 't') {
 623      $form['appearance']['toolbar_wizzard_used'] = array(
 624        '#type' => 'markup',
 625        '#value' => '<div>' . t('Used buttons') . '</div><div class="sortableList" id="groupLayout"></div><br/>',
 626        '#description' => t('Currently used buttons'),
 627      );
 628  
 629      drupal_add_js(array('cke_toolbar_buttons_all' => ckeditor_toolbar_buttons_all()), 'setting');
 630  
 631      $form['appearance']['toolbar_wizzard_all'] = array(
 632        '#type' => 'markup',
 633        '#value' => '<div>' . t('All buttons') . '</div><div id="allButtons" class="sortableList"></div><br/>',
 634        '#description' => t('All available buttons'),
 635      );
 636    }
 637  
 638    $plugin_list = ckeditor_load_plugins();
 639    $plugins = array();
 640    if (isset($profile->settings['loadPlugins'])) {
 641      foreach ($plugin_list AS $key => $val) {
 642        $plugins[$key] = $val['desc'];
 643      }
 644    }
 645    else {
 646      $default_plugins = array();
 647      foreach ($plugin_list AS $key => $val) {
 648        $plugins[$key] = $val['desc'];
 649          if (isset($val['default']) && $val['default'] == 't') {
 650            $default_plugins[] = $key;
 651          }
 652      }
 653    }
 654  
 655    $form['appearance']['loadPlugins'] = array(
 656      '#type' => 'checkboxes',
 657      '#title' => t('Plugins'),
 658      '#default_value' => isset($profile->settings['loadPlugins']) ? array_keys((array) $profile->settings['loadPlugins']) : $default_plugins,
 659      '#options' => $plugins,
 660      '#description' => t('Choose the plugins that you want to enable in CKEditor.')
 661    );
 662  
 663    $form['appearance']['expand'] = array(
 664      '#type' => 'radios',
 665      '#title' => t('Toolbar state on startup'),
 666      '#default_value' => !empty($profile->settings['expand']) ? $profile->settings['expand'] : 't',
 667      '#options' => array(
 668        't' => t('Expanded'),
 669        'f' => t('Collapsed')
 670      ),
 671      '#description' => t('The toolbar will start in an expanded or collapsed state.'),
 672    );
 673  
 674    $form['appearance']['width'] = array(
 675      '#type' => 'textfield',
 676      '#title' => t('Editor width'),
 677      '#default_value' => !empty($profile->settings['width']) ? $profile->settings['width'] : '100%',
 678      '#description' => t("Editor interface width in pixels or percent. Examples: 400, 100%."),
 679      '#size' => 40,
 680      '#maxlength' => 128,
 681    );
 682  
 683    $form['appearance']['lang'] = array(
 684      '#type' => 'select',
 685      '#title' => t('Language'),
 686      '#default_value' => !empty($profile->settings['lang']) ? $profile->settings['lang'] : 'en',
 687      '#options' => $lang_options,
 688      '#description' => t('The language for the CKEditor user interface.')
 689    );
 690  
 691    $form['appearance']['auto_lang'] = array(
 692      '#type' => 'radios',
 693      '#title' => t('Auto-detect language'),
 694      '#default_value' => !empty($profile->settings['auto_lang']) ? $profile->settings['auto_lang'] : 't',
 695      '#options' => array(
 696        't' => t('Enabled'),
 697        'f' => t('Disabled')
 698      ),
 699      '#description' => t('Automatically detect the user language.')
 700    );
 701  
 702    $form['appearance']['language_direction'] = array(
 703      '#type' => 'select',
 704      '#title' => t('Language direction'),
 705      '#default_value' => !empty($profile->settings['language_direction']) ? $profile->settings['language_direction'] : 'default',
 706      '#options' => array(
 707        'default' => t('Get from current locale (default)'),
 708        'ltr' => t('Left-To-Right'),// language like English
 709        'rtl' => t('Right-To-Left') // languages like Arabic
 710      ),
 711      '#description' => t(
 712        'Choose the language direction used in the editing area. Even when CKEditor automatically detects the user language and adjusts its user interface, the editing area is not automatically changed into the LTR or RTL mode. To be able to type LTR (like English) and RTL (like Arabic, Hebrew, Persian) content at the same time, please make sure that the <strong>!bidiltr</strong> and <strong>!bidirtl</strong> buttons are enabled in the toolbar.',
 713        array(
 714          '!bidiltr' => 'BidiLtr',
 715          '!bidirtl' => 'BidiRtl'
 716        )
 717      )
 718    );
 719  
 720    $form['output'] = array(
 721      '#type' => 'fieldset',
 722      '#title' => t('Cleanup and output'),
 723      '#collapsible' => TRUE,
 724      '#collapsed' => TRUE,
 725    );
 726  
 727    $form['output']['enter_mode'] = array(
 728      '#type' => 'select',
 729      '#title' => t('Enter mode'),
 730      '#default_value' => !empty($profile->settings['enter_mode']) ? $profile->settings['enter_mode'] : 'p',
 731      '#options' => array(
 732        'p' => '<p>',
 733        'br' => '<br>',
 734        'div' => '<div>'
 735      ),
 736      '#description' => t('Set which tag should be used by CKEditor when the <em>Enter</em> key is pressed.')
 737    );
 738  
 739    $form['output']['shift_enter_mode'] = array(
 740      '#type' => 'select',
 741      '#title' => t('Shift+Enter mode'),
 742      '#default_value' => !empty($profile->settings['shift_enter_mode']) ? $profile->settings['shift_enter_mode'] : 'br',
 743      '#options' => array(
 744        'p' => '<p>',
 745        'br' => '<br>',
 746        'div' => '<div>'
 747      ),
 748      '#description' => t('Set which tag should be used by CKEditor when the <em>Shift+Enter</em> key combination is pressed.')
 749    );
 750  
 751    $form['output']['font_format'] = array(
 752      '#type' => 'textfield',
 753      '#title' => t('Font formats'),
 754      '#default_value' => !empty($profile->settings['font_format']) ? $profile->settings['font_format'] : 'p;div;pre;address;h1;h2;h3;h4;h5;h6',
 755      '#size' => 40,
 756      '#maxlength' => 250,
 757      '#description' => t(
 758        'Semicolon-separated list of HTML font formats. Allowed values are: !allowed_values',
 759        array(
 760          '!allowed_values' => '<code>p;div;pre;address;h1;h2;h3;h4;h5;h6</code>'
 761        )
 762      )
 763    );
 764  
 765    if (!empty($profile->settings['formatting']['custom_formatting_options']))
 766    foreach ($profile->settings['formatting']['custom_formatting_options'] as $k => $v) {
 767      if ($v === 0) {
 768        unset($profile->settings['formatting']['custom_formatting_options'][$k]);
 769      }
 770    }
 771  
 772    $form['output']['custom_formatting'] = array(
 773      '#type' => 'radios',
 774      '#title' => t('Use custom formatting options'),
 775      '#default_value' => !empty($profile->settings['custom_formatting']) ? $profile->settings['custom_formatting'] : 'f',
 776      '#options' => array(
 777        't' => t('Yes'),
 778        'f' => t('No'),
 779      ),
 780    );
 781  
 782    $form['output']['formatting'] = array(
 783      '#type' => 'fieldset',
 784      '#title' => t('Custom formatting options'),
 785      '#tree' => TRUE,
 786    );
 787  
 788    $form['output']['formatting']['custom_formatting_options'] = array(
 789      '#type' => 'checkboxes',
 790      '#default_value' => isset($profile->settings['formatting']['custom_formatting_options']) ? array_keys((array) $profile->settings['formatting']['custom_formatting_options']) : array('indent' => 'indent', 'breakBeforeOpen' => 'breakBeforeOpen', 'breakAfterOpen' => 'breakAfterOpen', 'breakAfterClose' => 'breakAfterClose'),
 791      '#options' => array(
 792        'indent' => t('Indent the element contents.'),
 793        'breakBeforeOpen' => t('Break line before the opening tag.'),
 794        'breakAfterOpen' => t('Break line after the opening tag.'),
 795        'breakBeforeClose' => t('Break line before the closing tag.'),
 796        'breakAfterClose' => t('Break line after the closing tag.'),
 797        'pre_indent' => t('Indent the <code>&lt;pre&gt;</code> element contents.'),
 798      ),
 799    );
 800  
 801    $form['css'] = array(
 802      '#type' => 'fieldset',
 803      '#title' => t('CSS'),
 804      '#collapsible' => TRUE,
 805      '#collapsed' => TRUE
 806    );
 807  
 808    $form['css']['css_mode'] = array(
 809      '#type' => 'select',
 810      '#title' => t('Editor CSS'),
 811      '#default_value' => !empty($profile->settings['css_mode']) ? $profile->settings['css_mode'] : 'theme',
 812      '#options' => array(
 813        'theme' => t('Use theme CSS'),
 814        'self' => t('Define CSS'),
 815        'none' => t('CKEditor default')
 816      ),
 817      '#description' => t(
 818        'Defines the CSS to be used in the editor area.!title_theme_css &ndash; load the !style_css file from the current site theme.!title_define_css &ndash; enter the CSS file path below.!title_ckeditor_default &ndash; use the default editor CSS.',
 819        array(
 820          '!title_theme_css' => '<br /><strong>' . t('Use theme CSS') . '</strong>',
 821          '!title_define_css' => '<br /><strong>' . t('Define CSS') . '</strong>',
 822          '!title_ckeditor_default' => '<br /><strong>' . t('CKEditor default') . '</strong>',
 823          '!style_css' => '<code>style.css</code>'
 824        )
 825      )
 826    );
 827  
 828    $form['css']['css_path'] = array(
 829      '#type' => 'textfield',
 830      '#title' => t('CSS file path'),
 831      '#default_value' => !empty($profile->settings['css_path']) ? $profile->settings['css_path'] : "",
 832      '#size' => 40,
 833      '#maxlength' => 255,
 834      '#description' => t(
 835        'Enter the path to the CSS file (Example: !example1) or a list of CSS files separated with a comma (Example: !example2). Make sure you select the <strong>Define CSS</strong> option above.',
 836        array(
 837          '!example1' => '<code>"css/editor.css"</code>',
 838          '!example2' => '<code>"/themes/garland/style.css,http://example.com/style.css"</code>',
 839        )) .
 840        '<br />' .
 841        t(
 842          'Available placeholders:!h - host name (!host).!t - path to theme (!theme).',
 843          array(
 844            '!h' => '<br /><code>%h</code>',
 845            '!t' => '<br /><code>%t</code>',
 846            '!host' => base_path(),
 847            '!theme' => base_path() . path_to_theme() .'/'
 848          )
 849        )
 850    );
 851  
 852    $form['css']['css_style'] = array(
 853      '#type' => 'select',
 854      '#title' => t('Predefined styles'),
 855      '#default_value' => !empty($profile->settings['css_style']) ? $profile->settings['css_style'] : 'theme',
 856      '#options' => array(
 857        'theme' => t('Use theme ckeditor.styles.js'),
 858        'self' => t('Define path to ckeditor.styles.js'),
 859        'default' => t('CKEditor default')
 860      ),
 861      '#description' => t(
 862        'Define the location of the !ckeditor_styles_js_file file. It is used by the <strong>Style</strong> drop-down list available in the default toolbar. Copy the !ckeditor_styles_js_path file into your theme directory (!theme) and adjust it to your needs.',
 863        array(
 864          '!ckeditor_styles_js_file' => '<code>ckeditor.styles.js</code>',
 865          '!ckeditor_styles_js_path' => '<code>' . ckeditor_path(TRUE) .'/ckeditor.styles.js</code>',
 866          '!theme' => '<code>' . path_to_theme() . '/ckeditor.styles.js</code>'
 867        )
 868      )
 869    );
 870  
 871    $form['css']['styles_path'] = array(
 872      '#type' => 'textfield',
 873      '#title' => t('Predefined styles path'),
 874      '#default_value' => !empty($profile->settings['styles_path']) ? $profile->settings['styles_path'] : "",
 875      '#size' => 40,
 876      '#maxlength' => 255,
 877      '#description' => t(
 878          'Enter the path to a file with predefined styles (Example: !example1). Make sure you select the <strong>Define path to ckeditor.styles.js</strong> option above.',
 879          array(
 880            '!example1' => '<code>/ckeditor.styles.js</code>'
 881          )
 882        ) .
 883        '<br />' .
 884        t(
 885          'Available placeholders:!h &ndash;  host name (!host).!t &ndash; path to theme !theme.!m &ndash; path to the CKEditor module !module.',
 886          array(
 887            '!h' => '<br /><code>%h</code>',
 888            '!t' => '<br /><code>%t</code>',
 889            '!m' => '<br /><code>%m</code>',
 890            '!host' => '<code>' . base_path() . '</code>',
 891            '!theme' => '<code>' . base_path() . path_to_theme() . '/</code>',
 892            '!module' => '<code>' . drupal_get_path('module', 'ckeditor') . '</code>'
 893          )
 894        )
 895    );
 896  
 897    $form['ckeditor_upload_settings'] = array(
 898      '#type' => 'fieldset',
 899      '#title' => t('File browser settings'),
 900      '#collapsible' => TRUE,
 901      '#collapsed' => TRUE,
 902      '#description' => t(
 903        'Set the file browser settings. A file browser will allow you to browse the files stored on the server and embed them as links, images, or Flash movies. CKEditor is compatible with such Drupal modules as !imce, !ib, !webfm or !elfinder. CKEditor can be also integrated with !ckfinder, an advanced Ajax file manager.',
 904        array(
 905          '!imce' => l(t('IMCE'), 'http://drupal.org/project/imce'),
 906          '!ib' => l(t('Image Browser'), 'http://drupal.org/project/imagebrowser'),
 907          '!webfm' => l(t('Web File Manager'), 'http://drupal.org/project/webfm'),
 908          '!ckfinder' => l(t('CKFinder'), 'http://ckfinder.com'),
 909          '!elfinder' => l(t('elFinder'), 'http://drupal.org/project/elfinder')
 910        )
 911      )
 912    );
 913  
 914    $filebrowsers = array(
 915      'none' => t('None'),
 916      'ckfinder' => t('CKFinder'),
 917    );
 918  
 919    $filebrowsers_dialogs = array(
 920      '' => t('Same as in the Link dialog window'),
 921      'ckfinder' => t('CKFinder'),
 922    );
 923  
 924    if (module_exists('imce')) {
 925      $filebrowsers['imce'] = t('IMCE');
 926      $filebrowsers_dialogs['imce'] = t('IMCE');
 927    }
 928  
 929    if (module_exists('tinybrowser')) {
 930      $filebrowsers['tinybrowser'] = t('TinyBrowser');
 931      $filebrowsers_dialogs['tinybrowser'] = t('TinyBrowser');
 932    }
 933  
 934    if (module_exists('imagebrowser')) {
 935      $filebrowsers['ib'] = t('Image Browser');
 936      $filebrowsers_dialogs['ib'] = t('Image Browser');
 937    }
 938  
 939    if (module_exists('webfm_popup')) {
 940      $filebrowsers['webfm'] = t('Web File Manager');
 941      $filebrowsers_dialogs['webfm'] = t('Web File Manager');
 942    }
 943  
 944    if (module_exists('elfinder')) {
 945      $filebrowsers['elfinder'] = t('elFinder');
 946      $filebrowsers_dialogs['elfinder'] = t('elFinder');
 947    }
 948  
 949    $form['ckeditor_upload_settings']['filebrowser'] = array(
 950      '#type' => 'select',
 951      '#title' => t('File browser type (Link dialog window)'),
 952      '#default_value' => !empty($profile->settings['filebrowser']) ? $profile->settings['filebrowser'] : 'none',
 953      '#options' => $filebrowsers,
 954      '#description' => t('Select the file browser that you would like to use to upload files.'),
 955    );
 956  
 957    $form['ckeditor_upload_settings']['filebrowser_image'] = array(
 958      '#type' => 'select',
 959      '#title' => t('File browser type (Image dialog window)'),
 960      '#default_value' => !empty($profile->settings['filebrowser_image']) ? $profile->settings['filebrowser_image'] : 'none',
 961      '#options' => $filebrowsers_dialogs,
 962      '#description' => t('Select the file browser that you would like to use to upload images.'),
 963    );
 964  
 965    $form['ckeditor_upload_settings']['filebrowser_flash'] = array(
 966      '#type' => 'select',
 967      '#title' => t('File browser type (Flash dialog window)'),
 968      '#default_value' => !empty($profile->settings['filebrowser_flash']) ? $profile->settings['filebrowser_flash'] : 'none',
 969      '#options' => $filebrowsers_dialogs,
 970      '#description' => t('Select the file browser that you would like to use to upload Flash movies.'),
 971    );
 972  
 973    $current_user_files_path = empty($profile->settings['UserFilesPath']) ? "%b%f/" : $profile->settings['UserFilesPath'];
 974    $current_user_files_path = strtr($current_user_files_path, array("%f" => file_directory_path(), "%u" => "UID", "%b" => base_path(), "%n" => "UNAME"));
 975  
 976    $current_user_files_absolute_path = empty($profile->settings['UserFilesAbsolutePath']) ? "%d%b%f/" : $profile->settings['UserFilesAbsolutePath'];
 977    $current_user_files_absolute_path =  strtr($current_user_files_absolute_path, array("%f" => file_directory_path(), "%u" => "UID", "%b" => base_path(), "%d" => $_SERVER['DOCUMENT_ROOT'], "%n" => "UNAME"));
 978  
 979    if (variable_get('file_downloads', '') != FILE_DOWNLOADS_PRIVATE) {
 980  
 981      $form['ckeditor_upload_settings']['UserFilesPath'] = array(
 982        '#type' => 'textfield',
 983        '#prefix' => '<fieldset><legend>' . t('CKFinder settings') .'</legend>',
 984        '#title' => t('Path to uploaded files'),
 985        '#default_value' => !empty($profile->settings['UserFilesPath']) ? $profile->settings['UserFilesPath'] : "%b%f/",
 986        '#size' => 40,
 987        '#maxlength' => 255,
 988        '#description' => t('Path to uploaded files relative to the document root.') .
 989          '<br />' .
 990          t(
 991            'Available placeholders:!b &ndash; the base URL path of the Drupal installation <code>!base</code>.!f &ndash; Drupal file system path where the files are stored <code>!files</code>.!u &ndash; User ID.!n &ndash; Username.',
 992            array(
 993              '!n' => '<br /><code>%n</code>',
 994              '!u' => '<br /><code>%u</code>',
 995              '!f' => '<br/><code>%f</code>',
 996              '!b' => '<br/><code>%b</code>',
 997              '!files' => file_directory_path(),
 998              '!base' => base_path()
 999            )
1000          ) .
1001          '<br />' .
1002          t('Current path: !path',
1003            array(
1004              '!path' => '<code>' . $current_user_files_path . '</code>'
1005            )
1006          )
1007      );
1008  
1009      $form['ckeditor_upload_settings']['UserFilesAbsolutePath'] = array(
1010        '#type' => 'textfield',
1011        '#title' => t('Absolute path to uploaded files'),
1012        '#default_value' => !empty($profile->settings['UserFilesAbsolutePath']) ? $profile->settings['UserFilesAbsolutePath'] : "%d%b%f/",
1013        '#size' => 40,
1014        '#maxlength' => 255,
1015        '#suffix' => '</fieldset>',
1016        '#description' => t('The path to the local directory (on the server) which points to the path defined above. If left empty, CKEditor will try to discover the right path.') .
1017          '<br />' .
1018          t(
1019            'Available placeholders:!d &ndash; the server path to document root !root.!b &ndash; base URL path of the Drupal installation !base.!f &ndash; Drupal file system path where the files are stored !files.!u &ndash; User ID.!n &ndash; Username.',
1020            array(
1021              '!u' => '<br /><code>%u</code>',
1022              '!n' => '<br /><code>%n</code>',
1023              '!d' => '<br/><code>%d</code>',
1024              '!b' => '<br /><code>%b</code>',
1025              '!f' => '<br/><code>%f</code>',
1026              '!files' => '<code>' . file_directory_path() . '</code>',
1027              '!base' => '<code>' . base_path() . '</code>',
1028              '!root' => '<code>' . $_SERVER['DOCUMENT_ROOT'] . '</code>'
1029            )
1030          ) .
1031          '<br />' .
1032          t('Current path: !path',
1033            array(
1034              '!path' => '<code>' . $current_user_files_absolute_path . '</code>'
1035            )
1036          )
1037      );
1038    }
1039  
1040    if (variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE) {
1041      $form['ckeditor_upload_settings']['private_path_descrption'] = array(
1042        '#value' => '<div>' . t(
1043          'Setting a relative path to uploaded files was disabled because private downloads are enabled and thus this path is calculated automatically. To change the location of uploaded files in the private file system, edit the <strong>!url</strong>.',
1044          array(
1045            '!url' => l(t('CKEditor Global Profile'), 'admin/settings/ckeditor/editg')
1046          )
1047        ) .
1048        '</div>'
1049      );
1050    }
1051  
1052    $form['advanced'] = array(
1053      '#type' => 'fieldset',
1054      '#title' => t('Advanced options'),
1055      '#collapsible' => TRUE,
1056      '#collapsed' => TRUE,
1057    );
1058    $form['advanced']['ckeditor_load_method'] = array(
1059      '#type' => 'select',
1060      '#title' => t('Loading method'),
1061      '#default_value' => !empty($profile->settings['ckeditor_load_method']) ? $profile->settings['ckeditor_load_method'] : 'ckeditor.js',
1062      '#options' => _ckeditor_load_methods(),
1063      '#description' => t('Select the loading method of CKEditor. If the !ckeditor_basic_js file is used, only a small file is loaded initially and the rest of the editor is loaded later (see <strong>Loading timeout</strong>). This might be useful if CKEditor is disabled by default.',
1064        array(
1065          '!ckeditor_basic_js' => '<code>ckeditor_basic.js</code>'
1066        )
1067      )
1068    );
1069    $form['advanced']['ckeditor_load_time_out'] = array(
1070      '#type' => 'textfield',
1071      '#title' => t('Loading timeout'),
1072      '#default_value' => !empty($profile->settings['ckeditor_load_time_out']) ? $profile->settings['ckeditor_load_time_out'] : "0",
1073      '#size' => 40,
1074      '#maxlength' => 255,
1075      '#description' => t('The time to wait (in seconds) to load the full editor code after the page is loaded, if the !ckeditor_basic_js file is used. If set to zero, the editor is loaded on demand.',
1076        array(
1077          '!ckeditor_basic_js' => '<code>ckeditor_basic.js</code>'
1078        )
1079      )
1080    );
1081    $form['advanced']['forcePasteAsPlainText'] = array(
1082      '#type' => 'select',
1083      '#title' => t('Force pasting as plain text'),
1084      '#default_value' => !empty($profile->settings['forcePasteAsPlainText']) ? $profile->settings['forcePasteAsPlainText'] : "f",
1085      '#options' => array(
1086        't' => t('Enabled'),
1087        'f' => t('Disabled')
1088        ),
1089        '#description' => t('If enabled, HTML content will be automatically changed to plain text when pasting.'),
1090    );
1091    $form['advanced']['html_entities'] = array(
1092      '#type' => 'radios',
1093      '#title' => t('HTML Entities'),
1094      '#default_value' => !empty($profile->settings['html_entities']) ? $profile->settings['html_entities'] : 't',
1095      '#description' => t('Convert all applicable characters to HTML entities.'),
1096      '#options' => array(
1097        'f' => t('No'),
1098        't' => t('Yes')
1099      ),
1100    );
1101    $form['advanced']['scayt_autoStartup'] = array(
1102      '#type' => 'radios',
1103      '#title' => t('Spellchecker'),
1104      '#default_value' => !empty($profile->settings['scayt_autoStartup']) ? $profile->settings['scayt_autoStartup'] : 'f',
1105      '#description' => t('If enabled, turns on SCAYT (Spell Check As You Type) automatically after loading the editor.'),
1106      '#options' => array(
1107        'f' => t('No'),
1108        't' => t('Yes')
1109      ),
1110    );
1111    $form['advanced']['theme_config_js'] = array(
1112      '#type' => 'radios',
1113      '#title' => t('Load !ckeditor_config_js from the theme path',
1114        array(
1115          '!ckeditor_config_js' => '<code>ckeditor.config.js</code>'
1116        )
1117      ),
1118      '#default_value' => !empty($profile->settings['theme_config_js']) ? $profile->settings['theme_config_js'] : 'f',
1119      '#options' => array(
1120        't' => t('Yes'),
1121        'f' => t('No')
1122      ),
1123      '#description' => t('When enabled, the editor will try to load the !ckeditor_config_js file from the theme directory.',
1124        array(
1125          '!ckeditor_config_js' => '<code>ckeditor.config.js</code>'
1126        )
1127      ),
1128    );
1129    $form['advanced']['js_conf'] = array(
1130      '#type' => 'textarea',
1131      '#title' => t('Custom JavaScript configuration'),
1132      '#default_value' => !empty($profile->settings['js_conf']) ? $profile->settings['js_conf'] : "",
1133      '#cols' => 60,
1134      '#rows' => 5,
1135      '#description' => t(
1136          'In order to change CKEditor configuration globally, you should modify the !ckeditor_config configuration file. Sometimes it is required to change the CKEditor configuration for a single profile only. Use this box to define settings that are unique for this profile. Available options are listed in the !docs. Add the following code snippet to change the fonts available in the CKEditor <strong>Font</strong> and <strong>Size</strong> drop-down lists: <pre>@code</pre><strong>Warning</strong>: If you make a mistake here, CKEditor may not load correctly.',
1137          array(
1138            '!ckeditor_config' => '<code>' . drupal_get_path('module', 'ckeditor') . "/ckeditor.config.js</code>",
1139            '!docs' => l(t('CKEditor documentation'), 'http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html'),
1140            '@code' => "config.fontSize_sizes = '16/16px;24/24px;48/48px;'\nconfig.font_names = 'Arial;Times New Roman;Verdana'"
1141          )
1142        ),
1143      '#wysiwyg' => FALSE
1144    );
1145  
1146    $form['submit'] = array(
1147      '#type' => 'submit',
1148      '#value' => t('Save')
1149    );
1150  
1151    return $form;
1152  }
1153  
1154  /**
1155   * Profile validation.
1156   */
1157  function ckeditor_admin_profile_form_validate($form, &$form_state) {
1158    $edit =& $form_state['values'];
1159  
1160    //include mode and all other fields are empty, invalid
1161    if ($edit['excl_mode'] == 1 && empty($edit['excl'])) {
1162      form_set_error('excl_mode', t('Include mode selected, but no paths given. Enter at least one path where CKEditor should appear.'));
1163    }
1164    else {
1165      ckeditor_admin_profile_validate_fieldpaths('excl', $edit['excl']);
1166    }
1167  
1168    ckeditor_admin_profile_validate_fieldpaths('simple_incl', $edit['simple_incl']);
1169  
1170    if (!preg_match('/^\d+$/', trim($edit['min_rows']))) {
1171      form_set_error('min_rows', t('Minimum rows must be a valid number.'));
1172    }
1173  
1174    if ($edit['default'] == 't' && $edit['popup'] == 't') {
1175      form_set_error('popup', t('If CKEditor is enabled by default, the popup window must be disabled.'));
1176    }
1177  
1178    if ($edit['show_toggle'] == 't' && $edit['popup'] == 't') {
1179      form_set_error('popup', t('If toggle is enabled, the popup window must be disabled.'));
1180    }
1181  
1182    if (!$edit['name']) {
1183      form_set_error('name', t('You must give a profile name.'));
1184    }
1185    elseif (!preg_match('/^[A-Za-z0-9_]+$/', $edit['name'])) {
1186      form_set_error('name', t('Enter a valid profile name. Only alphanumeric and underscore characters are allowed.'));
1187    }
1188    elseif ($edit['name'] == 'CKEditor Global Profile') {
1189      form_set_error('name', t('This profile name is reserved. Please choose a different name.'));
1190    }
1191    elseif (!isset($edit['_profile']) || ($edit['_profile']->name != $edit['name'])) {
1192      $result = ckeditor_profile_load($edit['name']);
1193      if (!empty($result)) {
1194        form_set_error('name', t('The profile name must be unique. A profile with this name already exists.'));
1195      }
1196    }
1197  
1198    if (!preg_match('/^\d+%?$/', $edit['width'])) {
1199      form_set_error('width', t('Enter a valid width value. Examples: 400, 100%.'));
1200    }
1201  
1202    if (!empty($edit['css_path'])) {
1203      if ($edit['css_mode'] != 'self') {
1204        form_set_error('css_path', t('The CSS path is not empty. Please set the <strong>Editor CSS</strong> option to the <strong>Define CSS</strong> mode.'));
1205      }
1206      elseif (FALSE !== strpos($edit['css_path'], '"')) {
1207        form_set_error('css_path', t('Double quotes are not allowed in the CSS path.'));
1208      }
1209      elseif (substr($edit['css_path'], 0, 1) == "'" && substr($edit['css_path'], -1) == "'") {
1210        form_set_error('css_path', t('Enter a valid CSS path, do not surround it with quotes.'));
1211      }
1212    }
1213  
1214    if (!empty($edit['styles_path'])) {
1215      if ($edit['css_style'] != 'self') {
1216        form_set_error('styles_path', t('The path to predefined styles is not empty. Please set the <strong>Predefined styles</strong> option to the <strong>Define path to ckeditor.styles.js</strong> mode.'));
1217      }
1218      elseif (FALSE !== strpos($edit['styles_path'], '"')) {
1219        form_set_error('styles_path', t('Double quotes are not allowed in the styles path.'));
1220      }
1221      elseif (substr($edit['styles_path'], 0, 1) == "'" && substr($edit['styles_path'], -1) == "'") {
1222        form_set_error('styles_path', t('Enter a valid styles path, do not surround it with quotes.'));
1223      }
1224    }
1225  
1226    if (!empty($edit['font_format'])) {
1227      if (!preg_match("/^((p|div|pre|address|h1|h2|h3|h4|h5|h6);)*(p|div|pre|address|h1|h2|h3|h4|h5|h6)$/", $edit['font_format'])) {
1228        form_set_error('font_format', t('Enter a valid, semicolon-separated list of HTML font formats (no semicolon at the end of the list is expected).'));
1229      }
1230    }
1231  
1232    if (variable_get('file_downloads', '') !== FILE_DOWNLOADS_PRIVATE) {
1233      if (!empty($edit['UserFilesAbsolutePath']) && empty($edit['UserFilesPath'])) {
1234        form_set_error('UserFilesPath', t('The path to uploaded files is required.'));
1235      }
1236      if (!empty($edit['UserFilesPath']) && empty($edit['UserFilesAbsolutePath'])) {
1237        form_set_error('UserFilesPath', t('An absolute path to uploaded files is required.'));
1238      }
1239    }
1240    $load_methods=_ckeditor_load_methods();
1241    if (!isset($load_methods[$edit['ckeditor_load_method']])) {
1242      form_set_error('ckeditor_load_method', t('Set a valid loading method.'));
1243    }
1244    if (!preg_match('#\d+#', $edit['ckeditor_load_time_out'])) {
1245      form_set_error('ckeditor_load_time_out', t('Enter a valid loading timeout in seconds.'));
1246    }
1247  
1248    if (!preg_match('#^\s*\[(?:\s*(?:\{\s*[\w:\'" ,]*\s*\[(?:\s*([\'\"\"])(?:\w+|-)\1\s*[,]?\s*)+\]\s*\}|([\'\"\"])\/\2)\s*[,]?\s*)+\]\s*$#U', $edit['toolbar']) && !preg_match('#^\s*\[(?:\s*(?:\[(?:\s*([\'\"\"])(?:\w+|-)\1\s*[,]?\s*)+\]|([\'\"\"])\/\2)\s*[,]?\s*)+\]\s*$#', $edit['toolbar'])) {
1249      form_set_error('toolbar', t('Enter a valid toolbar configuration.'));
1250    }
1251  }
1252  
1253  function ckeditor_admin_profile_form_submit($form, &$form_state) {
1254    $edit =& $form_state['values'];
1255  
1256    if (isset($edit['_profile'])) {
1257      db_query("DELETE FROM {ckeditor_settings} WHERE name = '%s'", $edit['_profile']->name);
1258      db_query("DELETE FROM {ckeditor_role} WHERE name = '%s'", $edit['_profile']->name);
1259      drupal_set_message(t('Your CKEditor profile was updated.'));
1260    }
1261    else {
1262      drupal_set_message(t('Your CKEditor profile was created.'));
1263    }
1264  
1265    $settings = ckeditor_admin_values_to_settings($edit);
1266    db_query("INSERT INTO {ckeditor_settings} (name, settings) VALUES ('%s', '%s')", $edit['name'], $settings);
1267    ckeditor_rebuild_selectors($edit['name']);
1268    if (!empty($edit['rids'])) {
1269      foreach (array_keys($edit['rids']) as $rid) {
1270        if ($edit['rids'][$rid]!=0) {
1271          db_query("INSERT INTO {ckeditor_role} (name, rid) VALUES ('%s', %d)", $edit['name'], $rid);
1272        }
1273      }
1274    }
1275  
1276    $form_state['redirect'] = 'admin/settings/ckeditor';
1277  }
1278  
1279  function ckeditor_admin_global_profile_form($form_state, $mode = 'add') {
1280    module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
1281    if ($mode == 'edit') {
1282      $profile = ckeditor_profile_load('CKEditor Global Profile');
1283  
1284      $form['_profile'] = array(
1285        '#type' => 'value',
1286        '#value' => $profile,
1287      );
1288    }
1289    else {
1290      $profile = new stdClass();
1291    }
1292  
1293    if ($mode == 'add') {
1294      $data = ckeditor_profile_load('CKEditor Global Profile');
1295      if (!empty($data)) {
1296        drupal_set_message(t('The global profile already exists. Only one global profile is allowed.'), 'error');
1297        drupal_not_found();
1298      }
1299  
1300      $btn = t('Create a global profile');
1301    }
1302    else {
1303      $btn = t('Update the global profile');
1304    }
1305  
1306    $toolbar_wizard = !empty($profile->settings['toolbar_wizard']) ? $profile->settings['toolbar_wizard'] : 't';
1307    drupal_add_js(array('ckeditor_toolbar_wizard' => $toolbar_wizard), 'setting');
1308  
1309    $form['common'] = array(
1310      '#type' => 'fieldset',
1311      '#title' => t('Main setup'),
1312      '#collapsible' => TRUE,
1313      '#collapsed' => TRUE
1314    );
1315  
1316    $roles = ckeditor_sorted_roles();
1317    $rids = $rtext = array();
1318    foreach ($roles as $rid => $name) {
1319      $rids[] = $rid;
1320      $rtext[] = '<strong>'. $rid .' - </strong>'. $name;
1321    }
1322    $form['common']['rank'] = array(
1323      '#type' => 'textfield',
1324      '#title' => t('Role precedence'),
1325      '#default_value' => implode('>', $rids),
1326      '#description' => t('A user with <strong>multiple roles</strong> gets the permissions of the highest one. Sort role IDs according to their <strong>precedence from higher to lower</strong> by putting the ">" character in between.'),
1327    );
1328    if ($rids) {
1329      $form['common']['rank']['#description'] .= '<br />'. t('The following list contains the ID-name pairs of roles with access to CKEditor:') .'<div>'. implode('<br />', $rtext) .'</div>';
1330    }
1331    else {
1332      $form['common']['rank']['#description'] .= '<br />'. t(
1333        'You have not assigned the "access ckeditor" !permissions yet.',
1334        array(
1335          '!permissions' => l(t('permissions'), 'admin/user/permissions')
1336        )
1337      );
1338    }
1339  
1340    $form['ckeditor_exclude_settings'] = array(
1341      '#type' => 'fieldset',
1342      '#title' => t('Visibility settings'),
1343      '#collapsible' => TRUE,
1344      '#collapsed' => TRUE,
1345      '#description' => t('The following settings are combined with the visibility settings of the specific profile.'),
1346    );
1347  
1348    $form['ckeditor_exclude_settings']['excl_mode'] = array(
1349      '#type' => 'radios',
1350      '#title' => t('Use inclusion or exclusion mode'),
1351      '#default_value' => (empty($profile->settings['excl_mode']) || in_array($profile->settings['excl_mode'], array(0, 2))) ? 0 : 1,
1352      '#options' => array(
1353        '0' => t('Exclude'),
1354        '1' => t('Include')
1355      ),
1356      '#description' => t('Choose the way of disabling/enabling CKEditor on selected fields/paths (see below). Use <strong>Exclude</strong> to disable CKEditor on selected fields/paths. Use <strong>Include</strong> if you want to load CKEditor only on selected paths/fields.'),
1357    );
1358    /**
1359     * get excluded fields - so we can have normal textareas too
1360     * split the phrase by any number of commas or space characters,
1361     * which include " ", \r, \t, \n and \f
1362     */
1363    $form['ckeditor_exclude_settings']['excl'] = array(
1364      '#type' => 'textarea',
1365      '#title' => t('Fields to exclude/include'),
1366      '#cols' => 60,
1367      '#rows' => 5,
1368      '#prefix' => '<div style="margin-left:20px">',
1369      '#suffix' => '</div>',
1370      '#default_value' => !empty($profile->settings['excl']) ? $profile->settings['excl'] : '',
1371      '#description' => t('Enter the paths to the textarea fields for which you want to enable or disable CKEditor.') .
1372        ' ' .
1373        t(
1374          'See the !helppagelink for more information about defining field names. Short instruction is available below.',
1375          array(
1376            '!helppagelink' => l(t('Help page'), 'admin/help/ckeditor', array('fragment' => 'fieldinclexcl'))
1377          )
1378        ) .
1379        ' <ul><li>' .
1380        t('Path structure: <strong>theme_name:content_type@path.element_id</strong>') .
1381        '</li><li>' .
1382        t('The following wildcards are available: "*", "?".') .
1383        '</li><li>' .
1384        t('Content type and theme name is optional. You may even specify only path or field id.') .
1385        '</li><li>' .
1386        t('Examples:') .
1387        '<ul><li><em>garland:blog@*.edit-body</em> - ' .
1388        t('matches all fields of type "blog" called edit-body in garland theme, on any page.') .
1389        '<li><em>node/add/*.edit-user-*</em> - ' .
1390        t('matches fields starting with "edit-user-" on pages starting with "node/add/') .
1391        '</li></ul></li></ul>',
1392      '#wysiwyg' => FALSE,
1393    );
1394  
1395    $form['ckeditor_exclude_settings']['simple_incl'] = array(
1396      '#type' => 'textarea',
1397      '#title' => t('Force simplified toolbar on the following fields'),
1398      '#cols' => 60,
1399      '#rows' => 5,
1400      '#default_value' => !empty($profile->settings['simple_incl']) ? $profile->settings['simple_incl'] : '',
1401      '#description' => t('Enter the paths to the textarea fields for which you want to force the simplified toolbar.') .
1402        ' ' .
1403        t(
1404          'See the !helppagelink for more information about defining field names. Take a look at the exclusion settings (above) for a short instruction.',
1405          array(
1406            '!helppagelink' => l(t('Help page'), 'admin/help/ckeditor', array('fragment' => 'fieldinclexcl'))
1407          )
1408        ),
1409      '#wysiwyg' => FALSE,
1410    );
1411  
1412    $module_drupal_path = drupal_get_path('module', 'ckeditor');
1413  
1414    drupal_add_js($module_drupal_path . '/includes/ckeditor.admin.js', 'file');
1415  
1416    if ($toolbar_wizard == 't') {
1417      if (module_exists('jquery_ui')) {
1418        if (!module_exists('jquery_update')  || jquery_update_get_version() <= 1.2 )
1419          drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-1.4.4.min.js', 'core');
1420          if (jquery_ui_get_version() > 1.6) {
1421            jquery_ui_add(array('ui.sortable'));
1422          }
1423          else {
1424            drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-ui.min.js', 'file');
1425            drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.widget.min.js', 'file');
1426            drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.sortable.min.js', 'file');
1427          }
1428      }
1429      else {
1430        if (!module_exists('jquery_update') || jquery_update_get_version() <= 1.2 )
1431          drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-1.4.4.min.js', 'core');
1432        drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery-ui.min.js', 'file');
1433        drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.widget.min.js', 'file');
1434        drupal_add_js($module_drupal_path . '/includes/jqueryUI/jquery.ui.sortable.min.js', 'file');
1435      }
1436      drupal_add_js($module_drupal_path . '/includes/jqueryUI/sort.js', 'file');
1437    }
1438  
1439    $form['ckeditor_exclude_settings']['simple_toolbar'] = array(
1440      '#id' => 'edit-toolbar',
1441      '#type' => 'textarea',
1442      '#title' => t('Simplified toolbar'),
1443      '#default_value' => isset($profile->settings['simple_toolbar']) ? $profile->settings['simple_toolbar'] : "[ [ 'Format', 'Bold', 'Italic', '-', 'NumberedList','BulletedList', '-', 'Link', 'Unlink', 'Image' ] ]",
1444      '#wysiwyg' => FALSE,
1445      '#rows' => 15
1446    );
1447  
1448    if ($toolbar_wizard == 't') {
1449      $form['ckeditor_exclude_settings']['toolbar_wizzard_used'] = array(
1450        '#type' => 'markup',
1451        '#value' => '<div>' . t('Used buttons') . '</div><div class="sortableList" id="groupLayout"></div><br/>',
1452        '#description' => t('Currently used buttons'),
1453      );
1454  
1455      drupal_add_js(array('cke_toolbar_buttons_all' => ckeditor_toolbar_buttons_all(FALSE)), 'setting');
1456  
1457      $form['ckeditor_exclude_settings']['toolbar_wizzard_all'] = array(
1458        '#type' => 'markup',
1459        '#value' => '<div>' . t('All buttons') . '</div><div id="allButtons" class="sortableList"></div><br/>',
1460        '#description' => t('All available buttons'),
1461      );
1462    }
1463  
1464    $form['ckeditor_advanced_settings'] = array(
1465      '#type' => 'fieldset',
1466      '#title' => t('Advanced settings'),
1467      '#collapsible' => TRUE,
1468      '#collapsed' => TRUE,
1469    );
1470  
1471    $module_drupal_path = drupal_get_path('module', 'ckeditor');
1472  
1473    $form['ckeditor_advanced_settings']['ckeditor_path'] = array(
1474      '#type' => 'textfield',
1475      '#title' => t('Path to CKEditor'),
1476      '#default_value' =>  !empty($profile->settings['ckeditor_path']) ? $profile->settings['ckeditor_path'] : '%m/ckeditor',
1477      '#size' => 40,
1478      '#maxlength' => 128,
1479      '#description' => t(
1480          'The path to CKEditor (the WYSIWYG rich text editor downloaded from !ckeditorcom) relative to the document root.',
1481          array(
1482            '!ckeditorcom' => l(t('ckeditor.com'), 'http://ckeditor.com/download')
1483          )
1484        ) .
1485        '<br />'.
1486        t(
1487          'Available placeholders:!b &ndash; base URL path of the Drupal installation (!base).!m &ndash; base URL path where the CKEditor module is stored (!files).!l &ndash; base URL path to the libraries directory (!library).<br />Current path: !path',
1488          array(
1489            '!b' => '<br /><code>%b</code>',
1490            '!m' => '<br /><code>%m</code>',
1491            '!l' => '<br /><code>%l</code>',
1492            '!path' => '<code>' . ckeditor_path(FALSE) . '</code>',
1493            '!base' => '<code>' . base_path() . '</code>',
1494            '!files' => '<code>' . base_path() . $module_drupal_path . '</code>',
1495            '!library' => '<code>' . base_path() . 'sites/all/libraries/</code>'
1496          )
1497        ),
1498      '#required' => TRUE
1499    );
1500  
1501    $form['ckeditor_advanced_settings']['ckeditor_local_path'] = array(
1502      '#type' => 'textfield',
1503      '#title' => t('Local path to CKEditor'),
1504      '#default_value' =>  isset($profile->settings['ckeditor_local_path'])?$profile->settings['ckeditor_local_path']:'',
1505      '#size' => 40,
1506      '#maxlength' => 128,
1507      '#description' => t(
1508          'The path to the local directory (on the server) that points to the path defined above. Enter either an absolute server path or a path relative to the !indexphp file. If left empty, the CKEditor module will try to find the right path.',
1509          array(
1510            '!indexphp' => '<code>index.php</code>'
1511          )
1512        ) .
1513        '<br />' .
1514        t('Current path: !path',
1515          array(
1516            '!path' => '<code>' . ckeditor_path(TRUE) . '</code>'
1517          )
1518        )
1519    );
1520  
1521    $form['ckeditor_advanced_settings']['ckeditor_plugins_path'] = array(
1522      '#type' => 'textfield',
1523      '#title' => t('Path to the CKEditor plugins directory'),
1524      '#default_value' =>  !empty($profile->settings['ckeditor_plugins_path']) ? $profile->settings['ckeditor_plugins_path'] : '%m/plugins',
1525      '#size' => 40,
1526      '#maxlength' => 128,
1527      '#description' => t('Path to the CKEditor plugins directory relative to the document root.') .
1528        '<br />' .
1529        t(
1530          'Available placeholders:!b &ndash; the base URL path of the Drupal installation (!base).!m &ndash; the base URL path where the CKEditor module is stored (!files).!l &ndash; the base URL path to the libraries directory (!library).',
1531          array(
1532            '!b' => '<br /><code>%b</code>',
1533            '!m' => '<br /><code>%m</code>',
1534            '!l' => '<br /><code>%l</code>',
1535            '!base' => '<code>' . base_path() . '</code>',
1536            '!files' => '<code>' . base_path() . $module_drupal_path . '</code>' ,
1537            '!library' => '<code>' . base_path() . 'sites/all/libraries/</code>'
1538         )
1539        ) .
1540        '<br />' .
1541        t('Current path: !path',
1542          array(
1543            '!path' => '<code>' . ckeditor_plugins_path() . '</code>'
1544          )
1545        )
1546    );
1547  
1548    $form['ckeditor_advanced_settings']['ckeditor_plugins_local_path'] = array(
1549      '#type' => 'textfield',
1550      '#title' => t('Local path to the CKEditor plugins directory'),
1551      '#default_value' =>  isset($profile->settings['ckeditor_plugins_local_path'])?$profile->settings['ckeditor_plugins_local_path']:'',
1552      '#size' => 40,
1553      '#maxlength' => 128,
1554      '#description' => t(
1555        'The path to the local directory (on the server) that points to the path defined above. Enter either an absolute server path or a path relative to the !indexphp file. If left empty, the CKEditor module will try to find the right path.<br />Current path: !path',
1556        array(
1557          '!indexphp' => '<code>index.php</code>'
1558        )
1559      ) .
1560        '<br />' .
1561        t('Current path: !path',
1562          array(
1563            '!path' => '<code>' . ckeditor_plugins_path(TRUE) . '</code>'
1564          )
1565        )
1566    );
1567  
1568    $form['ckeditor_advanced_settings']['ckfinder_path'] = array(
1569      '#type' => 'textfield',
1570      '#title' => t('Path to CKFinder'),
1571      '#default_value' => !empty($profile->settings['ckfinder_path']) ? $profile->settings['ckfinder_path'] : '%m/ckfinder',
1572      '#size' => 40,
1573      '#maxlength' => 128,
1574      '#description' => t(
1575          'The path to CKFinder (AJAX based file manager downloaded from !ckfindercom) relative to the document root.',
1576          array(
1577            '!ckfindercom' => l(t('ckdiner.com'), 'http://ckfinder.com/download')
1578          )
1579        ) .
1580        '<br />' .
1581        t(
1582          'Available placeholders:!b &ndash; the base URL path of the Drupal installation (!base).!m &ndash; path where the CKEditor module is stored (!files).!l &ndash; path to the libraries directory (!library).',
1583          array(
1584            '!b' => '<br /><code>%b</code>',
1585            '!m' => '<br /><code>%m</code>',
1586            '!l' => '<br /><code>%l</code>',
1587            '!base' => '<code>' . base_path() . '</code>',
1588            '!files' => '<code>' . base_path() . $module_drupal_path . '</code>',
1589            '!library' => '<code>' . base_path() . 'sites/all/libraries/</code>'
1590          )
1591        ) .
1592        '<br />' .
1593        t('Current path: !path',
1594          array(
1595            '!path' => '<code>' . ckfinder_path() . '</code>'
1596          )
1597        )
1598    );
1599  
1600    $form['ckeditor_advanced_settings']['show_fieldnamehint'] = array(
1601      '#type' => 'radios',
1602      '#title' => t('Show field name hint below each rich text editor'),
1603      '#default_value' => !empty($profile->settings['show_fieldnamehint']) ? $profile->settings['show_fieldnamehint'] : 't',
1604      '#options' => array(
1605        't' => t('Yes'),
1606        'f' => t('No')
1607      ),
1608      '#description' => t('This only applies to users with the "administer ckeditor" permissions.'),
1609    );
1610  
1611    if (variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE) {
1612     $form['ckeditor_advanced_settings']['ckeditor_allow_download_private_files'] = array(
1613       '#type' => 'checkbox',
1614       '#title' => t('Enable access to files located in the private folder'),
1615       '#default_value' => !empty($profile->settings['ckeditor_allow_download_private_files']),
1616       '#return_value' => 't',
1617       '#description' => t(
1618         '<strong>Use this option with care.</strong> If checked, CKEditor will allow anyone knowing the URL to view a file located inside of the private path (!private_path), but only if there is no information about the file in the Drupal database. If the path below is specified, anyone will have access only to that location.',
1619         array(
1620           '!private_path' => '<code>' . realpath(file_directory_path()) . '</code>'
1621         )
1622       ),
1623       '#required' => FALSE
1624      );
1625  
1626      $current_private_dir = !empty($profile->settings['private_dir']) ? $profile->settings['private_dir'] : '';
1627      $form['ckeditor_advanced_settings']['private_dir'] = array(
1628        '#type' => 'textfield',
1629        '#title' => t('Location of files uploaded with CKEditor in  the private folder'),
1630        '#default_value' => !empty($profile->settings['private_dir']) ? $profile->settings['private_dir'] : '',
1631        '#size' => 40,
1632        '#maxlength' => 255,
1633        '#description' => t('The path relative to the location of the private directory where CKEditor should store uploaded files.') .
1634          '<br />' .
1635          t('System path to the private folder is: !system_path.',
1636            array(
1637              '!system_path' => '<code>' . realpath(file_directory_path()) . DIRECTORY_SEPARATOR . '</code>'
1638            )
1639          ) .
1640          '<br />' .
1641          t('Available wildcard characters: !u &ndash; User ID.!n &ndash; Username',
1642            array(
1643              '!u' => '<br/><code>%u</code>',
1644              '!n' => '<br /><code>%n</code>'
1645            )
1646          ) .
1647          '<br />' .
1648          t('Current path: !path',
1649            array(
1650              '!path' => '<code>' . $current_private_dir . ' (' . str_replace('/', DIRECTORY_SEPARATOR, file_create_path(str_replace(array('%u', '%n'), array('UID', 'UNAME'), $current_private_dir))) . ')</code>'
1651            )
1652          )
1653      );
1654    }
1655  
1656    if (function_exists('linktocontent_node_menu') && function_exists('pathfilter_filter')) {
1657      $form['ckeditor_advanced_settings']['linktoc'] = array(
1658        '#type' => 'select',
1659        '#options' => array('p' => t('Link to paths only'), 'n' => t('Link using internal: links'), 'pn' => t('Allow the user to select between paths and internal links')),
1660        '#title' => t('Path Filter & Link To Content integration'),
1661        '#default_value' => empty($profile->settings['linktoc']) ? 'p' : $profile->settings['linktoc'],
1662        '#description' => t(
1663          'With the !plink extension it is possible to use internal: links. By default the !link extension is linking to nodes using paths.',
1664          array(
1665            '!plink' => l(t('Path Filter'), 'http://drupal.org/project/pathfilter'),
1666            '!link' => l(t('Link To Content'), 'http://drupal.org/project/linktocontent')
1667          )
1668        )
1669      );
1670    }
1671  
1672    $form['ckeditor_advanced_settings']['toolbar_wizard'] = array(
1673      '#type' => 'radios',
1674      '#title' => t('Use toolbar Drag&Drop feature'),
1675      '#default_value' => !empty($profile->settings['toolbar_wizard']) ? $profile->settings['toolbar_wizard'] : 't',
1676      '#options' => array(
1677        't' => t('Enabled'),
1678        'f' => t('Disabled')
1679      ),
1680      '#description' => t('When enabled, the toolbar can be built by using the drag-and-drop feature. Otherwise you will need to enter the toolbar configuration manually to the text box.'),
1681    );
1682  
1683    $form['submit'] = array(
1684      '#type' => 'submit',
1685      '#value' => $btn
1686    );
1687  
1688    return $form;
1689  }
1690  
1691  function ckeditor_admin_global_profile_form_validate($form, &$form_state) {
1692    $edit =& $form_state['values'];
1693  
1694    if (!preg_match('#^\s*\[(?:\s*(?:\{\s*[\w:\'" ,]*\s*\[(?:\s*([\'\"\"])(?:\w+|-)\1\s*[,]?\s*)+\]\s*\}|([\'\"\"])\/\2)\s*[,]?\s*)+\]\s*$#U', $edit['simple_toolbar']) && !preg_match('#^\s*\[(?:\s*(?:\[(?:\s*([\'\"\"])(?:\w+|-)\1\s*[,]?\s*)+\]|([\'\"\"])\/\2)\s*[,]?\s*)+\]\s*$#', $edit['simple_toolbar'])) {
1695      form_set_error('simple_toolbar', t('Enter a valid toolbar configuration.'));
1696    }
1697  
1698    //include mode and all other fields are empty, invalid
1699    if ($edit['excl_mode'] == 1 && empty($edit['excl'])) {
1700      form_set_error('excl_mode', t('Include mode selected, but no paths given. Enter at least one path where CKEditor should appear.'));
1701    }
1702    else {
1703      ckeditor_admin_profile_validate_fieldpaths('excl', $edit['excl']);
1704    }
1705  
1706    ckeditor_admin_profile_validate_fieldpaths('simple_incl', $edit['simple_incl']);
1707  }
1708  
1709  function ckeditor_admin_global_profile_form_submit($form, &$form_state) {
1710    module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
1711    $edit =& $form_state['values'];
1712    $edit['name'] = 'CKEditor Global Profile';
1713  
1714    if (isset($edit['rank'])) {
1715      $edit['rank'] = explode('>', str_replace(' ', '', $edit['rank']));
1716    }
1717  
1718    if (isset($edit['_profile'])) {
1719      db_query("DELETE FROM {ckeditor_settings} WHERE name = '%s'", $edit['_profile']->name);
1720      db_query("DELETE FROM {ckeditor_role} WHERE name = '%s'", $edit['_profile']->name);
1721    }
1722  
1723    //strip whitespaces
1724    if (empty($edit['ckeditor_local_path'])) {
1725      $edit['ckeditor_local_path'] = '';
1726    }
1727    else {
1728      $edit['ckeditor_local_path'] = trim($edit['ckeditor_local_path']);
1729    }
1730  
1731    //strip slash from the end
1732    if (empty($edit['ckeditor_path'])) {
1733      $edit['ckeditor_path'] = '';
1734    }
1735    $edit['ckeditor_path'] = trim(rtrim($edit['ckeditor_path'], "/"));
1736    if ($edit['ckeditor_path'] && 0 !== strpos($edit['ckeditor_path'], "/") && 0 !== strpos($edit['ckeditor_path'], "%")) {
1737      //ensure that slash is at the beginning
1738      $edit['ckeditor_path'] = "/". $edit['ckeditor_path'];
1739    }
1740    //no slash at the end
1741    $edit['ckeditor_local_path'] = trim(rtrim($edit['ckeditor_local_path'], "/"));
1742  
1743    //strip whitespaces
1744    if (empty($edit['ckeditor_plugins_local_path'])) {
1745      $edit['ckeditor_plugins_local_path'] = '';
1746    }
1747    else {
1748      $edit['ckeditor_plugins_local_path'] = trim($edit['ckeditor_plugins_local_path']);
1749    }
1750  
1751    //strip slash from the end
1752    if (empty($edit['ckeditor_plugins_path'])) {
1753      $edit['ckeditor_plugins_path'] = '';
1754    }
1755    $edit['ckeditor_plugins_path'] = trim(rtrim($edit['ckeditor_plugins_path'], "/"));
1756    if ($edit['ckeditor_plugins_path'] && 0 !== strpos($edit['ckeditor_plugins_path'], "/") && 0 !== strpos($edit['ckeditor_plugins_path'], "%")) {
1757      //ensure that slash is at the beginning
1758      $edit['ckeditor_plugins_path'] = "/". $edit['ckeditor_plugins_path'];
1759    }
1760    //no slash at the end
1761    $edit['ckeditor_plugins_path'] = trim(rtrim($edit['ckeditor_plugins_path'], "/"));
1762  
1763    //strip slash from the end
1764    if (empty($edit['ckfinder_path'])) {
1765      $edit['ckfinder_path'] = '';
1766    }
1767    $edit['ckfinder_path'] = trim(rtrim($edit['ckfinder_path'], "/"));
1768    if ($edit['ckfinder_path'] && 0 !== strpos($edit['ckfinder_path'], "/") && 0 !== strpos($edit['ckfinder_path'], "%")) {
1769      //ensure that slash is at the beginning
1770      $edit['ckfinder_path'] = "/" . $edit['ckfinder_path'];
1771    }
1772  
1773    $settings = ckeditor_admin_values_to_settings($edit);
1774    db_query("INSERT INTO {ckeditor_settings} (name, settings) VALUES ('%s', '%s')", $edit['name'], $settings);
1775    ckeditor_rebuild_selectors($edit['name']);
1776  
1777    drupal_set_message(t('The CKEditor Global Profile was saved.'));
1778    $form_state['redirect'] = 'admin/settings/ckeditor';
1779  }
1780  
1781  /**
1782   * Converts an array of form values to a serialized array that does not
1783   * contain Drupal Form API values
1784   */
1785  function ckeditor_admin_values_to_settings($values) {
1786    $plugins = array();
1787    if (isset($values['loadPlugins'])) {
1788      $plugins = $values['loadPlugins'];
1789    }
1790    unset($values['name'], $values['rids'], $values['_profile'], $values['op'], $values['submit'], $values['form_build_id'], $values['form_token'], $values['form_id'], $values['loadPlugins']);
1791  
1792    module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
1793    $plugin_list = ckeditor_load_plugins();
1794    $values['loadPlugins'] = array();
1795    if (!empty($plugins)) {
1796      foreach (array_keys($plugins) as $plugin) {
1797        if ($plugins[$plugin] != '0') {
1798          $values['loadPlugins'][$plugin] = $plugin_list[$plugin];
1799        }
1800      }
1801    }
1802  
1803    return serialize($values);
1804  }
1805  
1806  function ckeditor_admin_profile_validate_fieldpaths($fieldname, $paths) {
1807    $myerrors = array();
1808  
1809    $rules = preg_split('/[\s,]+/', $paths);
1810  
1811    foreach ($rules as $rule) {
1812      $rule = trim($rule);
1813      if (!empty($rule) && strpos($rule, '.') === FALSE && strpos($rule, '/') === FALSE && strpos($rule, '-') === FALSE) {
1814        $myerrors[] = t(
1815          'Rule %rule is ambiguous: please append .* if %rule is a path or prepend *. if %rule is a field.',
1816          array(
1817            '%rule' => $rule
1818          )
1819        );
1820      }
1821    }
1822  
1823    if (!empty($myerrors)) {
1824      form_set_error($fieldname, check_plain(implode('<br/>', $myerrors)));
1825    }
1826  }
1827  
1828  function ckeditor_admin_profile_delete_form($form_state, $profile) {
1829    $form = array();
1830  
1831    $form['_profile'] = array(
1832      '#type' => 'value',
1833      '#value' => $profile,
1834    );
1835  
1836    $form['question'] = array(
1837      '#type' => 'item',
1838      '#value' => t(
1839        'Are you sure that you want to delete the CKEditor profile <strong>%profile</strong>?',
1840        array(
1841          '%profile' => $profile->name
1842        )
1843      )
1844    );
1845  
1846    $form['delete'] = array(
1847      '#type' => 'submit',
1848      '#id' => 'delete',
1849      '#value' => t('Delete'),
1850    );
1851  
1852    $form['back'] = array(
1853      '#type' => 'submit',
1854      '#id' => 'back',
1855      '#value' => t('Cancel'),
1856    );
1857  
1858    return $form;
1859  }
1860  
1861  function ckeditor_admin_profile_delete_form_submit($form, &$form_state) {
1862    $v =& $form_state['values'];
1863  
1864    if ($form_state['clicked_button']['#id'] == 'delete') {
1865      ckeditor_profile_delete($v['_profile']->name);
1866      drupal_set_message(t('The CKEditor profile was deleted.'));
1867    }
1868  
1869    $form_state['redirect'] = 'admin/settings/ckeditor';
1870  }
1871  
1872  /**
1873   * Rebuilds the regular expression that is used to match the inclusion/exclusion rules
1874   * and the simplified toolbar rules
1875   *
1876   * @param string $name Name of the profile to process. If omitted, all profiles are rebuilt
1877   */
1878  function ckeditor_rebuild_selectors($name = NULL) {
1879    if ($name == NULL) {
1880      $result = db_query("SELECT * FROM {ckeditor_settings}");
1881    }
1882    else {
1883      $result = db_query("SELECT * FROM {ckeditor_settings} WHERE name = '%s'", $name);
1884    }
1885  
1886    while (($data = db_fetch_object($result))) {
1887      if ($data->settings) {
1888        $settings = unserialize($data->settings);
1889        // [#654626]
1890        if (!isset($settings['excl'])) {
1891          $settings['excl'] = '';
1892        }
1893        if (!isset($settings['simple_incl'])) {
1894          $settings['simple_incl'] = '';
1895        }
1896  
1897        foreach (array('excl', 'simple_incl') as $var) {
1898          $settings[$var .'_regex'] = '';
1899          $rules = preg_split('/[\s,]+/', $settings[$var]);
1900          $regex = array();
1901  
1902          if (!empty($rules)) {
1903            foreach ($rules as $rule) {
1904              if (!empty($rule)) {
1905                $rule = ckeditor_parse_rule($rule);
1906                $regex[] = '(?:'. ckeditor_rule_to_regex($rule) .')';
1907              }
1908            }
1909  
1910            if (!empty($regex)) {
1911              $settings[$var .'_regex'] = '#'. implode('|', $regex) .'#';
1912            }
1913          }
1914        }
1915  
1916        db_query("UPDATE {ckeditor_settings} SET settings='%s' WHERE name='%s'", serialize($settings), $data->name);
1917      }
1918    }
1919  }
1920  
1921  function ckeditor_rule_create($nodetype = '*', $path = '*', $fieldname = '*') {
1922    global $theme;
1923  
1924    $rule = new stdClass();
1925    $rule->nodetype = $nodetype;
1926    $rule->path = $path;
1927    $rule->field = $fieldname;
1928    $rule->theme = $theme;
1929  
1930    return $rule;
1931  }
1932  
1933  function ckeditor_parse_rule($rule) {
1934    $ruleobj = new stdClass();
1935  
1936    $colonpos = strpos($rule, ':');
1937    if ($colonpos !== FALSE) {
1938      $ruleobj->theme = substr($rule, 0, $colonpos);
1939      $rule = substr($rule, $colonpos + 1);
1940    }
1941    else {
1942      $ruleobj->theme = '*';
1943    }
1944  
1945    $atpos = strpos($rule, '@');
1946    if ($atpos !== FALSE) {
1947      $ruleobj->nodetype = substr($rule, 0, $atpos);
1948      $rule = substr($rule, $atpos + 1);
1949    }
1950    else {
1951      $ruleobj->nodetype = '*';
1952    }
1953  
1954    $dotpos = strpos($rule, '.');
1955    if ($dotpos === FALSE) {
1956      if (strpos($rule, '/') === FALSE && strpos($rule, '-') !== FALSE) {
1957        // assume it's a field
1958        $ruleobj->path = '*';
1959        $ruleobj->field = $rule;
1960      }
1961      elseif (strpos($rule, '/') !== FALSE) {
1962        // assume it's a path
1963        $ruleobj->path = $rule;
1964        $ruleobj->field = '*';
1965      }
1966      else {
1967        return NULL;
1968      }
1969    }
1970    else {
1971      $ruleobj->path = substr($rule, 0, $dotpos);
1972      $ruleobj->field = str_replace('\.', '.', substr($rule, $dotpos + 1));
1973    }
1974  
1975    return $ruleobj;
1976  }
1977  
1978  function ckeditor_rule_to_regex($rule) {
1979    static $replace = array('\*' => '.*', '\?' => '.');
1980  
1981    $field = str_replace('.', '\.', $rule->field);
1982    $regex = '^'. preg_quote($rule->theme, '#') . ':' . preg_quote($rule->nodetype, '#') .'@'. preg_quote($rule->path, '#') .'\.'. preg_quote($field, '#') .'$';
1983    $regex = strtr($regex, $replace);
1984  
1985    return $regex;
1986  }
1987  
1988  function ckeditor_rule_to_string($rule) {
1989    $field = str_replace('.', '\.', $rule->field);
1990    $rulestr = $rule->theme . ':';
1991    if ($rule->nodetype != '*') {
1992      $rulestr .= $rule->nodetype .'@';
1993    }
1994    return $rulestr . $rule->path .'.'. $field;
1995  }
1996  
1997  /**
1998   * Remove a profile from the database.
1999   */
2000  function ckeditor_profile_delete($name) {
2001    db_query("DELETE FROM {ckeditor_settings} WHERE name = '%s'", $name);
2002    db_query("DELETE FROM {ckeditor_role} WHERE name = '%s'", $name);
2003  }
2004  
2005  function _ckeditor_load_methods() {
2006    $result = array('ckeditor.js' => 'ckeditor.js');
2007    if (file_exists(ckeditor_path(TRUE) . '/ckeditor_basic.js')) {
2008      $result['ckeditor_basic.js'] = 'ckeditor_basic.js';
2009    }
2010    if (file_exists(ckeditor_path(TRUE) . '/ckeditor_source.js')) {
2011      $result['ckeditor_source.js'] =  'ckeditor_source.js (' . t('for developers only') . ')';
2012    }
2013    return $result;
2014  }
2015  
2016  /*
2017   * Disable WYSIWYG module
2018   */
2019  function ckeditor_disable_wysiwyg($token) {
2020    if (!drupal_valid_token($token, 'ckeditorDisableWysiwyg')) {
2021      exit();
2022    }
2023    module_disable(array('wysiwyg'));
2024    drupal_set_message(t('The WYSIWYG module is disabled.'));
2025  
2026    drupal_goto('admin/settings/ckeditor');
2027  }
2028  
2029  /*
2030   * Get all available toolbar buttons
2031   */
2032  function ckeditor_toolbar_buttons_all($addPlugins = TRUE) {
2033    $path = base_path() . drupal_get_path('module', 'ckeditor');
2034  
2035    //CKEditor default buttons
2036    $buttons = array(
2037      'Source' => array('name' => 'Source', 'icon' => $path . '/images/buttons/source.png', 'title' => 'Source', 'row' => 1),
2038      'Save' => array('name' => 'Save', 'icon' => $path . '/images/buttons/save.png', 'title' => 'Save', 'row' => 1),
2039      'NewPage' => array('name' => 'NewPage', 'icon' => $path . '/images/buttons/newPage.png', 'title' => 'New Page', 'row' => 1),
2040      'Preview' => array('name' => 'Preview', 'icon' => $path . '/images/buttons/preview.png', 'title' => 'Preview', 'row' => 1),
2041      'Templates' => array('name' => 'Templates', 'icon' => $path . '/images/buttons/templates.png', 'title' => 'Templates', 'row' => 1),
2042      'Cut' => array('name' => 'Cut', 'icon' => $path . '/images/buttons/cut.png', 'title' => 'Cut', 'row' => 1),
2043      'Copy' => array('name' => 'Copy', 'icon' => $path . '/images/buttons/copy.png', 'title' => 'Copy', 'row' => 1),
2044      'Paste' => array('name' => 'Paste', 'icon' => $path . '/images/buttons/paste.png', 'title' => 'Paste', 'row' => 1),
2045      'PasteText' => array('name' => 'PasteText', 'icon' => $path . '/images/buttons/pastePlainText.png', 'title' => 'Paste as plain text', 'row' => 1),
2046      'PasteFromWord' => array('name' => 'PasteFromWord', 'icon' => $path . '/images/buttons/pasteWord.png', 'title' => 'Paste from Word', 'row' => 1),
2047      'Print' => array('name' => 'Print', 'icon' => $path . '/images/buttons/print.png', 'title' => 'Print', 'row' => 1),
2048      'SpellChecker' => array('name' => 'SpellChecker', 'icon' => $path . '/images/buttons/checkSpelling.png', 'title' => 'Check Spelling', 'row' => 1),
2049      'Scayt' => array('name' => 'Scayt', 'icon' => $path . '/images/buttons/checkSpelling.png', 'title' => 'Spell Check As you Type', 'row' => 1), //TODO sprawdzic ta opcje
2050      'Undo' => array('name' => 'Undo', 'icon' => $path . '/images/buttons/undo.png', 'title' => 'Undo', 'row' => 1),
2051      'Redo' => array('name' => 'Redo', 'icon' => $path . '/images/buttons/redo.png', 'title' => 'Redo', 'row' => 1),
2052      'Find' => array('name' => 'Find', 'icon' => $path . '/images/buttons/find.png', 'title' => 'Find', 'row' => 1),
2053      'Replace' => array('name' => 'Replace', 'icon' => $path . '/images/buttons/replace.png', 'title' => 'Replace', 'row' => 1),
2054      'SelectAll' => array('name' => 'SelectAll', 'icon' => $path . '/images/buttons/selectAll.png', 'title' => 'Select All', 'row' => 1),
2055      'RemoveFormat' => array('name' => 'RemoveFormat', 'icon' => $path . '/images/buttons/removeFormat.png', 'title' => 'Remove Format', 'row' => 1),
2056      'Form' => array('name' => 'Form', 'icon' => $path . '/images/buttons/form.png', 'title' => 'Form', 'row' => 1),
2057      'Checkbox' => array('name' => 'Checkbox', 'icon' => $path . '/images/buttons/checkbox.png', 'title' => 'Checkbox', 'row' => 1),
2058      'Radio' => array('name' => 'Radio', 'icon' => $path . '/images/buttons/radioButton.png', 'title' => 'Radio Button', 'row' => 1),
2059      'TextField' => array('name' => 'TextField', 'icon' => $path . '/images/buttons/textField.png', 'title' => 'Text Field', 'row' => 1),
2060      'Select' => array('name' => 'Select', 'icon' => $path . '/images/buttons/selectionField.png', 'title' => 'Selection Field', 'row' => 1),
2061      'Button' => array('name' => 'Button', 'icon' => $path . '/images/buttons/button.png', 'title' => 'Button', 'row' => 1),
2062      'ImageButton' => array('name' => 'ImageButton', 'icon' => $path . '/images/buttons/imageButton.png', 'title' => 'Image Button', 'row' => 1),
2063      'HiddenField' => array('name' => 'HiddenField', 'icon' => $path . '/images/buttons/hiddenField.png', 'title' => 'Hidden Field', 'row' => 1),
2064      'Bold' => array('name' => 'Bold', 'icon' => $path . '/images/buttons/bold.png', 'title' => 'Bold', 'row' => 2),
2065      'Italic' => array('name' => 'Italic', 'icon' => $path . '/images/buttons/italic.png', 'type' => 'command' , 'title' => 'Italic', 'row' => 2),
2066      'Underline' => array('name' => 'Underline', 'icon' => $path . '/images/buttons/underline.png', 'title' => 'Underline', 'row' => 2),
2067      'Strike' => array('name' => 'Strike', 'icon' => $path . '/images/buttons/strike.png', 'title' => 'Strike Through', 'row' => 2),
2068      'Subscript' => array('name' => 'Subscript', 'icon' => $path . '/images/buttons/subscript.png', 'title' => 'Subscript', 'row' => 2),
2069      'Superscript' => array('name' => 'Superscript', 'icon' => $path . '/images/buttons/superscript.png', 'title' => 'Superscript', 'row' => 2),
2070      'NumberedList' => array('name' => 'NumberedList', 'icon' => $path . '/images/buttons/numberedList.png', 'title' => 'Insert/Remove Numbered List', 'row' => 2),
2071      'BulletedList' => array('name' => 'BulletedList', 'icon' => $path . '/images/buttons/bulletedList.png', 'title' => 'Insert/Remove Bulleted List', 'row' => 2),
2072      'Outdent' => array('name' => 'Outdent', 'icon' => $path . '/images/buttons/decreaseIndent.png', 'title' => 'Decrease Indent', 'row' => 2),
2073      'Indent' => array('name' => 'Indent', 'icon' => $path . '/images/buttons/increaseIndent.png', 'title' => 'Increase Indent', 'row' => 2),
2074      'Blockquote' => array('name' => 'Blockquote', 'icon' => $path . '/images/buttons/blockQuote.png', 'title' => 'Block Quote', 'row' => 2),
2075      'CreateDiv' => array('name' => 'CreateDiv', 'icon' => $path . '/images/buttons/createDivContainer.png', 'title' => 'Create Div Container', 'row' => 2),
2076      'JustifyLeft' => array('name' => 'JustifyLeft', 'icon' => $path . '/images/buttons/leftJustify.png', 'title' => 'Left Justify', 'row' => 2),
2077      'JustifyCenter' => array('name' => 'JustifyCenter', 'icon' => $path . '/images/buttons/centerJustify.png', 'title' => 'Center Justify', 'row' => 2),
2078      'JustifyRight' => array('name' => 'JustifyRight', 'icon' => $path . '/images/buttons/rightJustify.png', 'title' => 'Right Justify', 'row' => 2),
2079      'JustifyBlock' => array('name' => 'JustifyBlock', 'icon' => $path . '/images/buttons/blockJustify.png', 'title' => 'Block Justify', 'row' => 2),
2080      'BidiLtr' => array('name' => 'BidiLtr', 'icon' => $path . '/images/buttons/bidiLeft.png', 'title' => 'Text direction from left to right', 'row' => 2),
2081      'BidiRtl' => array('name' => 'BidiRtl', 'icon' => $path . '/images/buttons/bidiRight.png', 'title' => 'Text direction from right to left', 'row' => 2),
2082      'Link' => array('name' => 'Link', 'icon' => $path . '/images/buttons/link.png', 'title' => 'Link', 'row' => 2),
2083      'Unlink' => array('name' => 'Unlink', 'icon' => $path . '/images/buttons/unlink.png', 'title' => 'Unlink', 'row' => 2),
2084      'Anchor' => array('name' => 'Anchor', 'icon' => $path . '/images/buttons/anchor.png', 'title' => 'Anchor', 'row' => 2),
2085      'Image' => array('name' => 'Image', 'icon' => $path . '/images/buttons/image.png', 'title' => 'Image', 'row' => 2),
2086      'Flash' => array('name' => 'Flash', 'icon' => $path . '/images/buttons/flash.png', 'title' => 'Flash', 'row' => 2),
2087      'Table' => array('name' => 'Table', 'icon' => $path . '/images/buttons/table.png', 'title' => 'Table', 'row' => 2),
2088      'HorizontalRule' => array('name' => 'HorizontalRule', 'icon' => $path . '/images/buttons/horizontalLine.png', 'title' => 'Insert Horizontal Line', 'row' => 2),
2089      'Smiley' => array('name' => 'Smiley', 'icon' => $path . '/images/buttons/smiley.png', 'title' => 'Smiley', 'row' => 2),
2090      'SpecialChar' => array('name' => 'SpecialChar', 'icon' => $path . '/images/buttons/specialCharacter.png', 'title' => 'Inseert Special Character', 'row' => 2),
2091      'PageBreak' => array('name' => 'PageBreak', 'icon' => $path . '/images/buttons/pageBreakPrinting.png', 'title' => 'Insert Page Break for Printing', 'row' => 2),
2092      'Styles' => array('name' => 'Styles', 'icon' => $path . '/images/buttons/styles.png', 'title' => 'Formatting Styles', 'row' => 3),
2093      'Format' => array('name' => 'Format', 'icon' => $path . '/images/buttons/format.png', 'title' => 'Paragraph Format', 'row' => 3),
2094      'Font' => array('name' => 'Font', 'icon' => $path . '/images/buttons/font.png', 'title' => 'Font Name', 'row' => 3),
2095      'FontSize' => array('name' => 'FontSize', 'icon' => $path . '/images/buttons/fontSize.png', 'title' => 'Font Size', 'row' => 3),
2096      'TextColor' => array('name' => 'TextColor', 'icon' => $path . '/images/buttons/textColor.png', 'title' => 'Text Color', 'row' => 3),
2097      'BGColor' => array('name' => 'BGColor', 'icon' => $path . '/images/buttons/backgroundColor.png', 'title' => 'Background Color', 'row' => 3),
2098      'Maximize' => array('name' => 'Maximize', 'icon' => $path . '/images/buttons/maximize.png', 'title' => 'Maximize', 'row' => 3),
2099      'ShowBlocks' => array('name' => 'ShowBlocks', 'icon' => $path . '/images/buttons/showBlocks.png', 'title' => 'Show Blocks', 'row' => 3),
2100      'Iframe' => array('name' => 'Iframe', 'icon' => $path . '/images/buttons/iframe.png', 'title' => 'IFrame', 'row' => 3),
2101      'About' => array('name' => 'About', 'icon' => $path . '/images/buttons/about.png', 'title' => 'About', 'row' => 3),
2102      '__spacer' => array('name' => FALSE, 'icon' => $path . '/images/buttons/spacer.png', 'title' => 'Spacer', 'row' => 4),
2103      '__group' => array('name' => FALSE, 'icon' => $path . '/images/buttons/group.png', 'title' => 'Group', 'row' => 4)
2104    );
2105  
2106    if ($addPlugins === TRUE) {
2107      $plugins = ckeditor_load_plugins(TRUE);
2108      foreach ($plugins as $plugin_name => $plugin) {
2109          if (!isset($plugin['buttons']) || $plugin['buttons'] == FALSE) continue;
2110          foreach ((array) $plugin['buttons'] as $button_name => $button) {
2111          $buttons[$button_name] = array('name' => $button_name, 'icon' => $plugin['path'] . $button['icon'], 'title' => t($button['label']), 'row' => 4);
2112          }
2113      }
2114    }
2115  
2116    return $buttons;
2117  }


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7