Projet

Général

Profil

Paste
Télécharger (84 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ckeditor / includes / ckeditor.admin.inc @ ed353324

1
<?php
2

    
3
/**
4
 * CKEditor - The text editor for the Internet - http://ckeditor.com
5
 * Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
6
 *
7
 * == BEGIN LICENSE ==
8
 *
9
 * Licensed under the terms of any of the following licenses of your
10
 * choice:
11
 *
12
 *  - GNU General Public License Version 2 or later (the "GPL")
13
 *    http://www.gnu.org/licenses/gpl.html
14
 *
15
 *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
16
 *    http://www.gnu.org/licenses/lgpl.html
17
 *
18
 *  - Mozilla Public License Version 1.1 or later (the "MPL")
19
 *    http://www.mozilla.org/MPL/MPL-1.1.html
20
 *
21
 * == END LICENSE ==
22
 *
23
 * @file
24
 * CKEditor Module for Drupal 7.x
25
 *
26
 * This module allows Drupal to replace textarea fields with CKEditor.
27
 *
28
 * CKEditor is an online rich text editor that can be embedded inside web pages.
29
 * It is a WYSIWYG (What You See Is What You Get) editor which means that the
30
 * text edited in it looks as similar as possible to the results end users will
31
 * see after the document gets published. It brings to the Web popular editing
32
 * features found in desktop word processors such as Microsoft Word and
33
 * OpenOffice.org Writer. CKEditor is truly lightweight and does not require any
34
 * kind of installation on the client computer.
35
 */
36

    
37
/**
38
 * Main administrative page
39
 */
40
function ckeditor_admin_main() {
41
  global $base_url;
42
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
43
  $editor_path = ckeditor_path('local');
44
  $ckconfig_file = $editor_path . '/config.js';
45

    
46
  //check if CKEditor plugin is installed
47
  if ($editor_path != '<URL>' && !_ckeditor_requirements_isinstalled()) {
48
    drupal_set_message(t(
49
            'Checking for !filename or !file.', array(
50
          '!filename' => '<code>' . $ckconfig_file . '</code>',
51
          '!file' => '<code>sites/all/libraries/ckeditor/ckeditor.js</code>'
52
            )
53
        ));
54
    drupal_set_message(t(
55
            '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.', array(
56
          '!ckeditorlink' => l(t('CKEditor homepage'), 'http://ckeditor.com/download'),
57
          '!readme' => l(t('README.txt'), $base_url . '/' . drupal_get_path('module', 'ckeditor') . '/README.txt', array('absolute' => TRUE)),
58
          '!ckeditorpath' => '<code>sites/all/modules/ckeditor/ckeditor</code>',
59
          '!ckeditorfile' => '<code>sites/all/modules/ckeditor/ckeditor/ckeditor.js</code>',
60
          '!ckeditorlibrary' => '<code>sites/all/libraries/ckeditor/ckeditor.js</code>',
61
          '!librarypath' => '<code>sites/all/libraries/ckeditor</code>'
62
            )
63
        ), 'error');
64
    drupal_set_message(t(
65
            'If you have CKEditor already installed, edit the <strong>!editg</strong> and update the CKEditor path.', array(
66
          '!editg' => l(t('CKEditor Global Profile'), 'admin/config/content/ckeditor/editg')
67
            )
68
        ), 'warning');
69

    
70
    return '';
71
  }
72

    
73
  if (module_exists('wysiwyg')) {
74
    drupal_set_message(t(
75
            '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).', array(
76
          '!wysiwygdisablelink' => l(t('click here to disable'), 'ckeditor/disable/wysiwyg/' . drupal_get_token('ckeditorDisableWysiwyg'))
77
            )
78
        ), 'warning');
79
  }
80

    
81
  //find profile other than Global
82
  $result = db_select('ckeditor_settings', 's')->fields('s', array('name'))->condition('name', 'CKEditor Global Profile', '<>')->range(0, 1)->execute()->fetchAssoc();
83
  if (!$result) {
84
    drupal_set_message(t('No CKEditor profiles found. Right now nobody is able to use CKEditor. Create a new profile below.'), 'error');
85
  }
86

    
87
  return ckeditor_profile_overview();
88
}
89

    
90
/**
91
 * Controller for CKEditor profiles.
92
 */
93
function ckeditor_profile_overview() {
94
  $output = '';
95
  $skins = ckeditor_load_skin_options();
96
  $global_profile = ckeditor_profile_load('CKEditor Global Profile');
97
  if (isset($global_profile->settings['skin']) && !array_key_exists($global_profile->settings['skin'], $skins)) {
98
    drupal_set_message(t('The <em>CKEditor Global Profile</em> profile is using %skin skin which cannot be found. Please <a href="@profile_settings">update your settings</a>.', array('%skin' => $global_profile->settings['skin'], '@profile_settings' => url('admin/config/content/ckeditor/editg'))), 'warning');
99
  }
100
  $profiles = ckeditor_profile_load();
101
  if ($profiles) {
102
    $access_ckeditor_roles = user_roles(FALSE, 'access ckeditor');
103
    $header = array(t('Profile'), t('Input format'), t('Operations'));
104
    $plugins = ckeditor_load_plugins();
105
    $disabled_plugins = array();
106
    foreach ($profiles as $p) {
107
      if ($p->name !== "CKEditor Global Profile") {
108
        if (isset($p->settings['loadPlugins']) && is_array($p->settings['loadPlugins']) && count($p->settings['loadPlugins']) > 0) {
109
          $changed = FALSE;
110
          foreach ($p->settings['loadPlugins'] as $plugin_name => $plugin_settings) {
111
            if (!array_key_exists($plugin_name, $plugins)) {
112
              if (isset($plugin_settings['active']) && $plugin_settings['active'] == 0) {
113
                continue;
114
              }
115
              if (!isset($disabled_plugins[$p->name])) {
116
                $disabled_plugins[$p->name] = array();
117
              }
118
              $p->settings['loadPlugins'][$plugin_name]['active'] = 0;
119
              $disabled_plugins[$p->name][] = $plugin_name;
120
              $changed = TRUE;
121
            }
122
          }
123
          if ($changed === TRUE) {
124
            db_update('ckeditor_settings')
125
                ->fields(array(
126
                  'settings' => serialize($p->settings)
127
                ))
128
                ->condition('name', $p->name, '=')
129
                ->execute();
130
          }
131
        }
132
        $rows[] = array(
133
          array('data' => $p->name, 'valign' => 'top'),
134
          array('data' => implode("<br />\n", $p->input_formats)),
135
          array(
136
            'data' =>
137
            l(t('edit'), 'admin/config/content/ckeditor/edit/' . urlencode($p->name)) . ' ' .
138
            l(t('clone'), 'admin/config/content/ckeditor/clone/' . urlencode($p->name)) . ' ' .
139
            l(t('delete'), 'admin/config/content/ckeditor/delete/' . urlencode($p->name)),
140
            'valign' => 'top'
141
          )
142
        );
143
      }
144
    }
145

    
146
    if (count($disabled_plugins) > 0) {
147
      $msg = t("The following plugins could not be found and were automatically disabled in CKEditor profiles:");
148
      foreach ($disabled_plugins as $profile_name => $profile_plugins) {
149
        $msg .= "<br/><br/>";
150
        $msg .= t("<b>Profile</b>: %profile_name", array("%profile_name" => $profile_name));
151
        $msg .= "<br/>";
152
        $msg .= t("<b>Plugins</b>: %profile_plugins", array("%profile_plugins" => implode(', ', $profile_plugins)));
153
      }
154
      drupal_set_message($msg, 'warning');
155
    }
156

    
157
    $output .= '<h3>' . t('Profiles') . '</h3>';
158
    $output .= theme('table', array("header" => $header, "rows" => $rows));
159
    $output .= '<p>' . l(t('Create a new profile'), 'admin/config/content/ckeditor/add') . '</p>';
160
  }
161
  else {
162
    drupal_set_message(t(
163
            'No profiles found. Click here to !create.', array(
164
          '!create' => l(t('create a new profile'), 'admin/config/content/ckeditor/add')
165
            )
166
        ), 'warning');
167
  }
168

    
169
  $rows = array();
170
  if (!isset($profiles['CKEditor Global Profile'])) {
171
    drupal_set_message(t(
172
            'The global profile can not be found. Click here to !create.', array(
173
          '!create' => l(t('create the global profile'), 'admin/config/content/ckeditor/addg')
174
            )
175
        ), 'warning');
176
  }
177
  else {
178
    $output .= "<h3>" . t("Global settings") . "</h3>";
179
    $rows[] = array(
180
      array('data' => t('CKEditor Global Profile')),
181
      array('data' => l(t('edit'), 'admin/config/content/ckeditor/editg'), 'valign' => 'top')
182
    );
183
    $output .= theme('table', array("header" => array(t('Profile'), t('Operations')), "rows" => $rows));
184
  }
185
  return $output;
186
}
187

    
188
/**
189
 * Form builder for a global profile
190
 */
191
function ckeditor_admin_global_profile_form($form, $form_state, $mode = 'add') {
192
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
193
  if ($mode == 'edit') {
194
    $profile = ckeditor_profile_load('CKEditor Global Profile');
195

    
196
    $form['_profile'] = array(
197
      '#type' => 'value',
198
      '#value' => $profile,
199
    );
200
  }
201
  else {
202
    $profile = new stdClass();
203
  }
204

    
205
  if ($mode == 'add') {
206
    $data = ckeditor_profile_load('CKEditor Global Profile');
207
    if (!empty($data)) {
208
      drupal_set_message(t('The global profile already exists. Only one global profile is allowed.'), 'error');
209
      drupal_not_found();
210
    }
211

    
212
    $btn = t('Create a global profile');
213
  }
214
  else {
215
    $btn = t('Update the global profile');
216
  }
217

    
218
  $orig_formats = filter_formats();
219
  $formats = array();
220
  foreach ($orig_formats AS $format) {
221
    $formats[$format->format] = $format->name;
222
  }
223

    
224
  $drupal_base_path = ckeditor_base_path('relative');
225
  $drupal_library_path = ckeditor_library_path('relative');
226
  $module_drupal_path = ckeditor_module_path('relative');
227
  $skin_options = ckeditor_load_skin_options();
228

    
229
  $form['appearance'] = array(
230
    '#type' => 'fieldset',
231
    '#title' => t('Editor appearance'),
232
    '#collapsible' => TRUE,
233
    '#collapsed' => FALSE,
234
  );
235

    
236
  //if skin is not set or not exists select default skin (moono or skin) or first on the skin list
237
  if (empty($profile->settings['skin']) || (!empty($profile->settings['skin']) && !array_key_exists($profile->settings['skin'], $skin_options))) {
238
    $profile->settings['skin'] = ckeditor_default_skin();
239
  }
240

    
241
  $form['appearance']['skin'] = array(
242
    '#type' => 'select',
243
    '#title' => t('Skin'),
244
    '#default_value' => $profile->settings['skin'],
245
    '#options' => $skin_options,
246
    '#description' => t('Choose a CKEditor skin.'),
247
  );
248

    
249
  $form['ckeditor_advanced_settings'] = array(
250
    '#type' => 'fieldset',
251
    '#title' => t('Advanced settings'),
252
    '#collapsible' => TRUE,
253
    '#collapsed' => FALSE,
254
  );
255

    
256
  $current_path = ckeditor_path('relative');
257
  if ($current_path == '<URL>') {
258
    $current_path = ckeditor_path('url');
259
  }
260
  $form['ckeditor_advanced_settings']['ckeditor_path'] = array(
261
    '#type' => 'textfield',
262
    '#title' => t('Path to CKEditor'),
263
    '#default_value' => !empty($profile->settings['ckeditor_path']) ? $profile->settings['ckeditor_path'] : '%m/ckeditor',
264
    '#size' => 40,
265
    '#maxlength' => 128,
266
    '#description' => t(
267
        'The path to CKEditor (the WYSIWYG rich text editor downloaded from !ckeditorcom). Provide a path relative to the document root, unless CKEditor is located on an external URL. In such case enter the full URL to a folder with CKEditor.<br />The simplest way to have the editor running is to use CDN, to use it set: !cdn', array(
268
      '!ckeditorcom' => l(t('ckeditor.com'), 'http://ckeditor.com/download'),
269
      '!cdn' => '<strong>//cdn.ckeditor.com/4.4.3/full-all</strong>'
270
        )
271
    ) .
272
    '<br /><br /> ' .
273
    t('Available placeholders:!b &ndash; path of the Drupal installation (!base) !m &ndash; path where the CKEditor module is stored (!module).!l &ndash; path to the libraries directory (!library).', array(
274
      '!b' => '<br /><code>%b</code>',
275
      '!m' => '<br /><code>%m</code>',
276
      '!l' => '<br /><code>%l</code>',
277
      '!base' => '<code>' . $drupal_base_path . '</code>',
278
      '!module' => '<code>' . $module_drupal_path . '</code>',
279
      '!library' => '<code>' . $drupal_library_path . '</code>',
280
        )
281
    ) .
282
    '<br /> ' .
283
    t('Current path: !path', array(
284
      '!path' => '<code>' . $current_path . '</code>'
285
        )
286
    ),
287
    '#required' => TRUE
288
  );
289

    
290
  $local_path = ckeditor_path('local');
291
  if ($local_path == '<URL>') {
292
    $local_path = t('CKEditor is loaded from URL. Local path is not available.');
293
  }
294
  $form['ckeditor_advanced_settings']['ckeditor_local_path'] = array(
295
    '#type' => 'textfield',
296
    '#title' => t('Local path to CKEditor'),
297
    '#default_value' => isset($profile->settings['ckeditor_local_path']) ? $profile->settings['ckeditor_local_path'] : '',
298
    '#size' => 40,
299
    '#maxlength' => 128,
300
    '#description' => t(
301
        '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.', array(
302
      '!indexphp' => '<code>index.php</code>'
303
        )
304
    ) .
305
    '<br /> ' .
306
    t('Current path: !path', array(
307
      '!path' => '<code>' . $local_path . '</code>'
308
        )
309
    )
310
  );
311

    
312
  $form['ckeditor_advanced_settings']['ckeditor_plugins_path'] = array(
313
    '#type' => 'textfield',
314
    '#title' => t('Path to the CKEditor plugins directory'),
315
    '#default_value' => !empty($profile->settings['ckeditor_plugins_path']) ? $profile->settings['ckeditor_plugins_path'] : '%m/plugins',
316
    '#size' => 40,
317
    '#maxlength' => 128,
318
    '#description' => t('Path to the CKEditor plugins directory relative to the document root.') .
319
    '<br />' .
320
    t('Available placeholders:!b &ndash; path of the Drupal installation (!base) !m &ndash; the base URL path where the CKEditor module is stored (!module).!l &ndash; the base URL path to the libraries directory (!library)', array(
321
      '!b' => '<br /><code>%b</code>',
322
      '!m' => '<br /><code>%m</code>',
323
      '!l' => '<br /><code>%l</code>',
324
      '!base' => '<code>' . $drupal_base_path . '</code>',
325
      '!module' => '<code>' . $module_drupal_path . '</code>',
326
      '!library' => '<code>' . $drupal_library_path . '</code>',
327
        )
328
    ) .
329
    '<br /> ' .
330
    t('Current path: !path', array(
331
      '!path' => '<code>' . ckeditor_plugins_path('relative') . '</code>'
332
        )
333
    )
334
  );
335

    
336
  $form['ckeditor_advanced_settings']['ckeditor_plugins_local_path'] = array(
337
    '#type' => 'textfield',
338
    '#title' => t('Local path to the CKEditor plugins directory'),
339
    '#default_value' => isset($profile->settings['ckeditor_plugins_local_path']) ? $profile->settings['ckeditor_plugins_local_path'] : '',
340
    '#size' => 40,
341
    '#maxlength' => 128,
342
    '#description' => t(
343
        '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.', array(
344
      '!indexphp' => '<code>index.php</code>'
345
        )
346
    ) .
347
    '<br /> ' .
348
    t('Current path: !path', array(
349
      '!path' => '<code>' . ckeditor_plugins_path('local') . '</code>'
350
        )
351
    )
352
  );
353

    
354
  $form['ckeditor_advanced_settings']['ckfinder_path'] = array(
355
    '#type' => 'textfield',
356
    '#title' => t('Path to CKFinder'),
357
    '#default_value' => !empty($profile->settings['ckfinder_path']) ? $profile->settings['ckfinder_path'] : '%m/ckfinder',
358
    '#size' => 40,
359
    '#maxlength' => 128,
360
    '#description' => t(
361
        'The path to CKFinder (AJAX based file manager downloaded from !ckfindercom) relative to the document root.', array(
362
      '!ckfindercom' => l(t('ckfinder.com'), 'http://cksource.com/ckfinder')
363
        )
364
    ) .
365
    '<br />' .
366
    t('Available placeholders:!b &ndash; path of the Drupal installation (!base) !m &ndash; path where the CKEditor module is stored (!module).!l &ndash; path to the libraries directory (!library)', array(
367
      '!b' => '<br /><code>%b</code>',
368
      '!m' => '<br /><code>%m</code>',
369
      '!l' => '<br /><code>%l</code>',
370
      '!base' => '<code>' . $drupal_base_path . '</code>',
371
      '!module' => '<code>' . $module_drupal_path . '</code>',
372
      '!library' => '<code>' . $drupal_library_path . '</code>'
373
        )
374
    ) .
375
    '<br /> ' .
376
    t('Current path: !path', array(
377
      '!path' => '<code>' . ckfinder_path('relative') . '</code>'
378
        )
379
    )
380
  );
381

    
382
  $form['ckeditor_advanced_settings']['ckfinder_local_path'] = array(
383
    '#type' => 'textfield',
384
    '#title' => t('Local path to CKFinder'),
385
    '#default_value' => isset($profile->settings['ckfinder_local_path']) ? $profile->settings['ckfinder_local_path'] : '',
386
    '#size' => 40,
387
    '#maxlength' => 128,
388
    '#description' => t(
389
        '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.', array(
390
      '!indexphp' => '<code>index.php</code>'
391
        )
392
    ) .
393
    '<br /> ' .
394
    t('Current path: !path', array(
395
      '!path' => '<code>' . ckfinder_path('local') . '</code>'
396
        )
397
    )
398
  );
399

    
400
  //@todo DOWNLOAD API
401
  if (variable_get('file_default_scheme', '') == 'private') {
402
    $form['ckeditor_advanced_settings']['ckeditor_allow_download_private_files'] = array(
403
      '#type' => 'checkbox',
404
      '#title' => t('Enable access to files located in the private folder'),
405
      '#default_value' => !empty($profile->settings['ckeditor_allow_download_private_files']),
406
      '#return_value' => 't',
407
      '#description' => t(
408
          '<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.', array(
409
        '!private_path' => '<code>' . variable_get('file_private_path', '') . '</code>'
410
          )
411
      ),
412
      '#required' => FALSE
413
    );
414
    $current_private_dir = !empty($profile->settings['private_dir']) ? $profile->settings['private_dir'] : '';
415
    $form['ckeditor_advanced_settings']['private_dir'] = array(
416
      '#type' => 'textfield',
417
      '#title' => t('Location of files uploaded with CKEditor to the private folder'),
418
      '#default_value' => !empty($profile->settings['private_dir']) ? $profile->settings['private_dir'] : '',
419
      '#size' => 40,
420
      '#maxlength' => 255,
421
      '#description' => t('The path relative to the location of the private directory where CKEditor should store uploaded files.') .
422
      '<br />' .
423
      t('Available wildcard characters:!u &ndash; User ID.!n &ndash; Username', array(
424
        '!u' => '<br/><code>%u</code>',
425
        '!n' => '<br /><code>%n</code>'
426
          )
427
      ) .
428
      '<br />' .
429
      t('System path to the private folder is: !system_path.', array(
430
        '!system_path' => '<code>' . realpath(variable_get('file_private_path', conf_path() . '/files')) . DIRECTORY_SEPARATOR . '</code>'
431
          )
432
      )
433
    );
434
  }
435

    
436
  if (function_exists('linktocontent_node_menu') && function_exists('pathfilter_filter')) {
437
    $form['ckeditor_advanced_settings']['linktoc'] = array(
438
      '#type' => 'select',
439
      '#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')),
440
      '#title' => t('Path Filter & Link To Content integration'),
441
      '#default_value' => empty($profile->settings['linktoc']) ? 'p' : $profile->settings['linktoc'],
442
      '#description' => t(
443
          'With the !plink extension it is possible to use internal: links. By default the !link extension is linking to nodes using paths.', array(
444
        '!plink' => l(t('Path Filter'), 'http://drupal.org/project/pathfilter'),
445
        '!link' => l(t('Link To Content'), 'http://drupal.org/project/linktocontent')
446
          )
447
      )
448
    );
449
  }
450

    
451
  $form['ckeditor_advanced_settings']['ckeditor_aggregate'] = array(
452
    '#type' => 'radios',
453
    '#title' => t('Aggregate <code>ckeditor.js</code>'),
454
    '#default_value' => !empty($profile->settings['ckeditor_aggregate']) ? $profile->settings['ckeditor_aggregate'] : 'f',
455
    '#options' => array(
456
      't' => t('Enabled'),
457
      'f' => t('Disabled')
458
    ),
459
    '#description' => t('When enabled, <code>ckeditor.js</code> will be aggregated if JavaScript aggregation is enabled. <strong>Not recommended</strong>.'),
460
  );
461

    
462
  $form['ckeditor_advanced_settings']['toolbar_wizard'] = array(
463
    '#type' => 'radios',
464
    '#title' => t('Use toolbar Drag&Drop feature'),
465
    '#default_value' => !empty($profile->settings['toolbar_wizard']) ? $profile->settings['toolbar_wizard'] : 't',
466
    '#options' => array(
467
      't' => t('Enabled'),
468
      'f' => t('Disabled')
469
    ),
470
    '#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.'),
471
  );
472

    
473
  $form['submit'] = array(
474
    '#type' => 'submit',
475
    '#value' => $btn
476
  );
477

    
478
  return $form;
479
}
480

    
481
/**
482
 * Form validation for a global profile
483
 */
484
function ckeditor_admin_global_profile_form_validate($form, &$form_state) {
485

    
486
}
487

    
488
/**
489
 * Submit form for a global profile
490
 */
491
function ckeditor_admin_global_profile_form_submit($form, &$form_state) {
492
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
493
  $edit = & $form_state['values'];
494
  $edit['name'] = 'CKEditor Global Profile';
495

    
496
  if (isset($edit['_profile'])) {
497
    ckeditor_profile_delete($edit['_profile']->name);
498
  }
499

    
500
  //strip whitespaces
501
  if (empty($edit['ckeditor_local_path'])) {
502
    $edit['ckeditor_local_path'] = '';
503
  }
504
  else {
505
    $edit['ckeditor_local_path'] = trim($edit['ckeditor_local_path']);
506
  }
507

    
508
  //strip slash from the end
509
  if (empty($edit['ckeditor_path'])) {
510
    $edit['ckeditor_path'] = '';
511
  }
512
  $edit['ckeditor_path'] = trim(rtrim($edit['ckeditor_path'], "/"));
513
  if ($edit['ckeditor_path'] && 0 !== strpos($edit['ckeditor_path'], "/") && 0 !== strpos($edit['ckeditor_path'], "%") && !preg_match("|^http(s)?://|i", $edit['ckeditor_path'])) {
514
    //ensure that slash is at the beginning
515
    $edit['ckeditor_path'] = "/" . $edit['ckeditor_path'];
516
  }
517
  //no slash at the end
518
  $edit['ckeditor_local_path'] = trim(rtrim($edit['ckeditor_local_path'], "/"));
519

    
520
  //strip whitespaces
521
  if (empty($edit['ckeditor_plugins_local_path'])) {
522
    $edit['ckeditor_plugins_local_path'] = '';
523
  }
524
  else {
525
    $edit['ckeditor_plugins_local_path'] = trim($edit['ckeditor_plugins_local_path']);
526
  }
527

    
528
  //strip slash from the end
529
  if (empty($edit['ckeditor_plugins_path'])) {
530
    $edit['ckeditor_plugins_path'] = '';
531
  }
532
  $edit['ckeditor_plugins_path'] = trim(rtrim($edit['ckeditor_plugins_path'], "/"));
533
  if ($edit['ckeditor_plugins_path'] && 0 !== strpos($edit['ckeditor_plugins_path'], "/") && 0 !== strpos($edit['ckeditor_plugins_path'], "%")) {
534
    //ensure that slash is at the beginning
535
    $edit['ckeditor_plugins_path'] = "/" . $edit['ckeditor_plugins_path'];
536
  }
537
  //no slash at the end
538
  $edit['ckeditor_plugins_path'] = trim(rtrim($edit['ckeditor_plugins_path'], "/"));
539

    
540
  //strip slash from the end
541
  if (empty($edit['ckfinder_path'])) {
542
    $edit['ckfinder_path'] = '';
543
  }
544
  $edit['ckfinder_path'] = trim(rtrim($edit['ckfinder_path'], "/"));
545
  if ($edit['ckfinder_path'] && 0 !== strpos($edit['ckfinder_path'], "/") && 0 !== strpos($edit['ckfinder_path'], "%")) {
546
    //ensure that slash is at the beginning
547
    $edit['ckfinder_path'] = "/" . $edit['ckfinder_path'];
548
  }
549

    
550
  //no slash at the end
551
  $edit['ckfinder_local_path'] = trim(rtrim($edit['ckfinder_local_path'], "/"));
552

    
553
  $settings = ckeditor_admin_values_to_settings($edit);
554
  db_insert('ckeditor_settings')
555
      ->fields(array(
556
        "name" => $edit["name"],
557
        "settings" => $settings
558
      ))
559
      ->execute();
560

    
561
  drupal_set_message(t('The CKEditor global profile was saved.'));
562
  $form_state['redirect'] = 'admin/config/content/ckeditor';
563
}
564

    
565
/**
566
 * Form builder for a profile
567
 */
568
function ckeditor_admin_profile_form($form, $form_state, $task, $profile = NULL) {
569
  global $theme;
570

    
571
  if ($profile != NULL) {
572
    $form['_profile'] = array(
573
      '#type' => 'value',
574
      '#value' => $profile,
575
    );
576
  }
577
  else {
578
    $profile = new stdClass();
579
  }
580

    
581
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
582

    
583
  $editor_path = ckeditor_path('relative');
584
  $editor_local_path = ckeditor_path('local');
585
  $editor_url_path = ckeditor_path('url');
586
  $module_drupal_path = ckeditor_module_path('relative');
587
  $module_drupal_url_path = ckeditor_module_path('url');
588

    
589
  drupal_add_js(array('ckeditor_version' => ckeditor_get_version()), 'setting');
590

    
591
  $lang_options = ckeditor_load_lang_options();
592

    
593
  // Attach the administration CSS.
594
  $form['#attached'] = array(
595
    'css' => array(
596
      drupal_get_path('module', 'ckeditor') . '/css/ckeditor.admin.css',
597
    ),
598
  );
599

    
600
  $form['basic'] = array(
601
    '#type' => 'fieldset',
602
    '#title' => t('Basic setup'),
603
    '#collapsible' => TRUE,
604
    '#collapsed' => TRUE
605
  );
606

    
607
  switch ($task) {
608
    case 'clone':
609
      //load all profiles to check their names
610
      $profiles = ckeditor_profile_load();
611
      $oldname = $profile->name;
612
      $maxsize = 128;   //default max name length
613

    
614
      $res = array();
615
      $pat = "/^(.*?)_([0-9]+)$/";
616
      if (preg_match($pat, $oldname, $res)) {     // oldname like 'name_nr'
617
        $name = $res[1];
618
        $num = $res[2] + 1;
619
      }
620
      else {
621
        $name = $oldname;
622
        $num = 2;
623
      }
624

    
625
      $newname = substr($name, 0, $maxsize - 3) . '_' . $num;   // +limit
626
      while (isset($profiles[$newname])) {            //find next free number
627
        $num++;
628
        $newname = substr($name, 0, $maxsize - 3) . '_' . $num;
629
      }
630
      break;
631
    case 'edit':
632
      $newname = $profile->name;
633
      break;
634
  }
635

    
636
  $global_profile = ckeditor_profile_load('CKEditor Global Profile');
637
  $toolbar_wizard = !empty($global_profile->settings['toolbar_wizard']) ? $global_profile->settings['toolbar_wizard'] : 't';
638
  drupal_add_js(array('ckeditor_toolbar_wizard' => $toolbar_wizard), 'setting');
639

    
640
  $form['basic']['name'] = array(
641
    '#type' => 'textfield',
642
    '#title' => t('Profile name'),
643
    '#default_value' => !empty($profile->name) ? $newname : '',
644
    '#size' => 40,
645
    '#maxlength' => 128,
646
    '#description' => t('Enter a name for this profile. This name is only visible within the CKEditor administration page.'),
647
    '#required' => TRUE
648
  );
649

    
650
  $orig_formats = filter_formats();
651

    
652
  if ($task == 'edit' && !empty($profile->name)) {
653
    $used_formats = db_select('ckeditor_input_format', 'f')->fields('f', array("format"))->distinct()->condition("f.name", array($profile->name), 'NOT IN')->execute()->fetchAllAssoc('format');
654
  }
655
  else {
656
    $profile->input_formats = array();
657
    $used_formats = db_select('ckeditor_input_format', 'f')->fields('f', array("format"))->distinct()->execute()->fetchAllAssoc('format');
658
  }
659

    
660
  $formats = array();
661
  $input_format_config_links = array();
662
  foreach ($orig_formats AS $format) {
663
    if (($task == 'edit' && !empty($profile->input_formats) && array_key_exists($format->format, $profile->input_formats)) || !array_key_exists($format->format, $used_formats)) {
664
      $formats[$format->format] = $format->name;
665
      $input_format_config_links[$format->format] = array("name" => $format->name, "config_url" => url("admin/config/content/formats/" . $format->format));
666
    }
667
  }
668

    
669
  $form['basic']['input_formats'] = array(
670
    '#id' => 'input-formats',
671
    '#type' => 'checkboxes',
672
    '#title' => t('Text formats'),
673
    '#default_value' => !empty($profile->input_formats) ? array_keys((array) $profile->input_formats) : array(),
674
    '#options' => $formats,
675
    '#description' => t('Choose the text formats where you want to load CKEditor.')
676
  );
677

    
678
  $form['security'] = array(
679
    '#type' => 'fieldset',
680
    '#title' => t('Security'),
681
    '#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>',
682
    '#collapsible' => TRUE,
683
    '#collapsed' => TRUE
684
  );
685

    
686
  $form['security']['filters'] = array(
687
    '#id' => 'security-filters',
688
    '#type' => 'container'
689
  );
690

    
691
  $form['security']['filters']['__header'] = array(
692
    '#type' => 'item',
693
    '#title' => t('Security filters'),
694
    '#description' => t(
695
      'Below is a list of security filters along with their status for each text format.<br /><br />The following statuses are available: !img_enabled - the filter is configured for a given text format and will be run on the content during the filtering process. !img_disabled - the filter is disabled for a given text format and will not be run on the content during the filtering process.<br /><br />In order to modify the security filters settings for each of the text formats, you need to visit the text format configuration sections as listed below: !elem_format_config', array(
696
      '!img_enabled' => '</br><img src="' . $module_drupal_path . '/images/tick.png"/>',
697
      '!img_disabled' => '</br><img src="' . $module_drupal_path . '/images/delete.png"/>',
698
      '!elem_format_config' => '<ul class="text-formats-config"></ul>'
699
        )
700
    ),
701
    '#weight' => -10
702
  );
703

    
704
  //get text formats filters
705
  $input_format_filters = array();
706
  foreach ($formats AS $key => $value) {
707
    $input_format_filters[$key] = array();
708
    $filters = filter_list_format($key);
709
    foreach ($filters as $filter_name => $filter_settings) {
710
      if ($filter_settings->status == 1) {
711
        $input_format_filters[$key][$filter_name] = TRUE;
712
      }
713
    }
714
  }
715
  drupal_add_js(array('text_format_filters' => $input_format_filters, 'text_formats_config_links' => $input_format_config_links), 'setting');
716

    
717
  $security_filters = ckeditor_security_filters();
718
  _ckeditor_admin_profile_form_security_filters($form, $profile, $security_filters);
719

    
720
  $form['security']['ss'] = array(
721
    '#type' => 'radios',
722
    '#title' => t('Security settings'),
723
    '#default_value' => isset($profile->settings['ss']) ? $profile->settings['ss'] : '2',
724
    '#options' => array(
725
      '2' => t('Always run security filters for CKEditor.'),
726
      '1' => t('Run security filters only when CKEditor is set to start automatically.'),
727
    ),
728
    '#description' => t('There are two ways of starting CKEditor: automatically and manually (via toggle). 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. Choose this option only if you can detect various attacks (mainly XSS) by yourself just by looking at the HTML code.'),
729
  );
730

    
731
  $form['appearance'] = array(
732
    '#type' => 'fieldset',
733
    '#title' => t('Editor appearance'),
734
    '#collapsible' => TRUE,
735
    '#collapsed' => TRUE,
736
  );
737

    
738
  $ui_colors = array(
739
    "default" => t('CKEditor default'),
740
    "custom" => t('Select manually')
741
  );
742
  if (function_exists('color_get_palette')) {
743
    // apparently $theme is not initialized (?)
744
    if (empty($theme)) {
745
      init_theme();
746
    }
747
    $palette = @color_get_palette($theme, FALSE); //[#652274]
748
    $color_palette['default'] = '#D3D3D3';
749
    if (!empty($palette)) {
750
      if (!empty($palette['base'])) {
751
        $color_palette['color_base'] = $palette['base'];
752
        $ui_colors["color_base"] = t('Color module: base');
753
      }
754
      if (!empty($palette['top'])) {
755
        $color_palette['color_top'] = $palette['top'];
756
        $ui_colors["color_top"] = t('Color module: top');
757
      }
758
      if (!empty($palette['bottom'])) {
759
        $color_palette['color_bottom'] = $palette['bottom'];
760
        $ui_colors["color_bottom"] = t('Color module: bottom');
761
      }
762
    }
763
    drupal_add_js(array('ckeditor_uicolor' => $color_palette), 'setting');
764
  }
765

    
766
  if ($editor_path == '<URL>') {
767
    drupal_add_js($editor_url_path . '/ckeditor.js', 'external');
768
  }
769
  else {
770
    drupal_add_js('window.CKEDITOR_BASEPATH = "' . $editor_path . '/"', array('type' => 'inline', 'weight' => -100));
771
    drupal_add_js($editor_url_path . '/ckeditor.js', array('type' => 'file', 'preprocess' => FALSE));
772
  }
773
  drupal_add_js($module_drupal_url_path . '/ckeditor.config.js', 'file');
774
  drupal_add_js($module_drupal_url_path . '/includes/ckeditor.admin.js', 'file');
775

    
776
  if ($toolbar_wizard == 't') {
777
    drupal_add_library('system', 'ui.widget');
778
    drupal_add_library('system', 'ui.sortable');
779
    drupal_add_js($module_drupal_url_path . '/includes/jqueryUI/sort.js', 'file');
780
  }
781

    
782
  $form['appearance']['toolbar'] = array(
783
    '#type' => 'textarea',
784
    '#title' => t('Toolbar'),
785
    '#default_value' => !empty($profile->settings['toolbar']) ? $profile->settings['toolbar'] : '',
786
    '#description' => t('Load sample toolbar: !toolbars', array("!toolbars" => '<a href="#" id="cke_toolbar_DrupalBasic" class="cke_load_toolbar">' . t('Basic') . '</a> | <a href="#" id="cke_toolbar_DrupalAdvanced" class="cke_load_toolbar">' . t('Advanced') . '</a> | <a href="#" id="cke_toolbar_DrupalFull" class="cke_load_toolbar">' . t('Full') . '</a>')),
787
    '#wysiwyg' => FALSE,
788
    '#rows' => 15
789
  );
790

    
791
  if ($toolbar_wizard == 't') {
792
    $form['appearance']['toolbar_wizzard_used'] = array(
793
      '#markup' => '<div>' . t('Current toolbar') . '</div><div class="sortableList" id="groupLayout"></div><br/>',
794
      '#description' => t('Currently used buttons'),
795
    );
796

    
797
    drupal_add_js(array('cke_toolbar_buttons_all' => ckeditor_toolbar_buttons_all()), 'setting');
798

    
799
    $form['appearance']['toolbar_wizzard_all'] = array(
800
      '#markup' => '<div>' . t('Available buttons') . '</div><div id="allButtons" class="sortableList"></div><br/>',
801
      '#description' => t('All available buttons'),
802
    );
803
  }
804

    
805
  $form['appearance']['expand'] = array(
806
    '#type' => 'radios',
807
    '#title' => t('Toolbar state on startup'),
808
    '#default_value' => !empty($profile->settings['expand']) ? $profile->settings['expand'] : 't',
809
    '#options' => array(
810
      't' => t('Expanded'),
811
      'f' => t('Collapsed')
812
    ),
813
    '#description' => t('The toolbar will start in an expanded or collapsed state.'),
814
  );
815

    
816
  $form['appearance']['default'] = array(
817
    '#type' => 'radios',
818
    '#title' => t('Default editor state'),
819
    '#default_value' => !empty($profile->settings['default']) ? $profile->settings['default'] : 't',
820
    '#options' => array(
821
      't' => t('Enabled'),
822
      'f' => t('Disabled')
823
    ),
824
    '#description' => t('Default editor state. If disabled, the rich text editor may still be enabled by using toggle.'),
825
  );
826

    
827
  $form['appearance']['show_toggle'] = array(
828
    '#type' => 'radios',
829
    '#title' => t('Show the disable/enable rich text editor toggle'),
830
    '#default_value' => !empty($profile->settings['show_toggle']) ? $profile->settings['show_toggle'] : 't',
831
    '#options' => array(
832
      't' => t('Show'),
833
      'f' => t('Hide')
834
    ),
835
    '#description' => t('Whether or not to show the disable/enable rich text editor toggle below the textarea.'),
836
  );
837

    
838
  $form['appearance']['uicolor'] = array(
839
    '#type' => 'select',
840
    '#title' => t('User interface color'),
841
    '#default_value' => !empty($profile->settings['uicolor']) ? $profile->settings['uicolor'] : 'default',
842
    '#options' => $ui_colors,
843
  );
844

    
845
  if (!isset($global_profile->settings['skin']) || !file_exists($editor_local_path . '/skins/' . $global_profile->settings['skin'])) {
846
    $global_profile->settings['skin'] = ckeditor_default_skin();
847
  }
848
  $skinframe_url = url('admin/config/content/ckeditor/skinframe', array(
849
    'query' => array(
850
      'token' => drupal_get_token('ckeditorSkinframeCall'),
851
      'skin' => $global_profile->settings['skin'],
852
      'uicolor' => (!empty($profile->settings['uicolor_user']) && $profile->settings['uicolor'] == 'custom') ? ltrim($profile->settings['uicolor_user'], '#') : 'D3D3D3'
853
    )
854
  ));
855
  $form['appearance']['skinframe'] = array(
856
    '#markup' => '<iframe frameborder="0" id="skinframe" marginheight="0" marginwidth="0" src="' . $skinframe_url . '" style="height:430px;width:700px;"></iframe><br/>',
857
    '#description' => '',
858
  );
859
  $form['appearance']['uicolor_user'] = array(
860
    '#type' => 'hidden',
861
    '#default_value' => !empty($profile->settings['uicolor_user']) ? $profile->settings['uicolor_user'] : 'default',
862
  );
863

    
864
  $plugin_list = ckeditor_load_plugins();
865
  $plugins = array();
866
  if (isset($profile->settings['loadPlugins'])) {
867
    foreach ($plugin_list AS $key => $val) {
868
      $plugins[$key] = $val['desc'];
869
    }
870
  }
871
  else {
872
    $default_plugins = array();
873
    foreach ($plugin_list AS $key => $val) {
874
      $plugins[$key] = $val['desc'];
875
      if (isset($val['default']) && $val['default'] == 't') {
876
        $default_plugins[] = $key;
877
      }
878
    }
879
  }
880

    
881
  $form['appearance']['loadPlugins'] = array(
882
    '#type' => 'checkboxes',
883
    '#title' => t('Plugins'),
884
    '#default_value' => isset($profile->settings['loadPlugins']) ? array_keys((array) $profile->settings['loadPlugins']) : $default_plugins,
885
    '#options' => $plugins,
886
    '#description' => t('Choose the plugins that you want to enable in CKEditor.')
887
  );
888

    
889
  if ($editor_local_path != '<URL>' && file_exists($editor_local_path . '/plugins/divarea/plugin.js')) {
890
    $form['appearance']['use_divarea'] = array(
891
      '#type' => 'radios',
892
      '#title' => t('"Div-based" editor'),
893
      '#default_value' => !empty($profile->settings['use_divarea']) ? $profile->settings['use_divarea'] : 'f',
894
      '#options' => array(
895
        't' => t('Enabled'),
896
        'f' => t('Disabled')
897
      ),
898
      '#description' => t("Loading editor into <code>div</code> instead of <code>iframe</code>.")
899
    );
900
  }
901

    
902
  $form['appearance']['width'] = array(
903
    '#type' => 'textfield',
904
    '#title' => t('Editor width'),
905
    '#default_value' => !empty($profile->settings['width']) ? $profile->settings['width'] : '100%',
906
    '#description' => t("Editor interface width in pixels or percent. Examples: 400, 100%."),
907
    '#size' => 40,
908
    '#maxlength' => 128,
909
  );
910

    
911
  $form['appearance']['lang'] = array(
912
    '#type' => 'select',
913
    '#title' => t('Language'),
914
    '#default_value' => !empty($profile->settings['lang']) ? $profile->settings['lang'] : 'en',
915
    '#options' => $lang_options,
916
    '#description' => t('The language for the CKEditor user interface.')
917
  );
918

    
919
  $form['appearance']['auto_lang'] = array(
920
    '#type' => 'radios',
921
    '#title' => t('Auto-detect language'),
922
    '#default_value' => !empty($profile->settings['auto_lang']) ? $profile->settings['auto_lang'] : 't',
923
    '#options' => array(
924
      't' => t('Enabled'),
925
      'f' => t('Disabled')
926
    ),
927
    '#description' => t('Automatically detect the user language.')
928
  );
929

    
930
  $form['appearance']['language_direction'] = array(
931
    '#type' => 'select',
932
    '#title' => t('Language direction'),
933
    '#default_value' => !empty($profile->settings['language_direction']) ? $profile->settings['language_direction'] : 'default',
934
    '#options' => array(
935
      'default' => t('Get from current locale (default)'),
936
      'ltr' => t('Left-To-Right'), // language like English
937
      'rtl' => t('Right-To-Left') // languages like Arabic
938
    ),
939
    '#description' => t(
940
        '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.', array(
941
      '!bidiltr' => 'BidiLtr',
942
      '!bidirtl' => 'BidiRtl'
943
        )
944
    )
945
  );
946

    
947
  $form['acf'] = array(
948
    '#type' => 'fieldset',
949
    '#title' => t('Advanced content filter'),
950
    '#description' => t('Configure input data filtering in CKEditor. See !link for more information about ACF.', array(
951
        '!link' => l(t('this blog post'), 'http://ckeditor.com/blog/Upgrading-to-CKEditor-4.1')
952
      )),
953
    '#collapsible' => TRUE,
954
    '#collapsed' => TRUE
955
  );
956

    
957
  $form['acf']['allowed_content'] = array(
958
    '#type' => 'radios',
959
    '#title' => t('Advanced content filter'),
960
    '#description' => t('<strong>Example:</strong> if only Bold and Link buttons are enabled, only !strong and !a tags will be allowed. Any !b tags will automatically be converted into !strong. The !img tag will not be allowed, unless the Image button is added to the toolbar.', array(
961
    '!strong' => '<code>&lt;strong&gt;</code>',
962
    '!a' => '<code>&lt;a&gt;</code>',
963
    '!img' => '<code>&lt;img&gt;</code>',
964
    '!b' => '<code>&lt;b&gt;</code>'
965
  )).'<br /><br />'.
966
    t('<strong>Warning:</strong> CKEditor will not use the set of tags associated with text format. Only the buttons enabled in the toolbar and optional plugins will determine which tags/attributes/styles are handled by CKEditor. Enabling ACF in CKEditor does not affect server-side filtering done by Drupal in any way.'),
967

    
968
    '#default_value' => !empty($profile->settings['allowed_content']) ? $profile->settings['allowed_content'] : 't',
969
    '#options' => array(
970
      't' => t('Enabled'),
971
      'f' => t('Disabled'),
972
    ),
973
  );
974
  $form['acf']['allowed_content']['t']['#description'] = t('CKEditor will only allow tags/attributes/styles provided by CKEditor features. Disallowed content will be removed directly by CKEditor. When configured properly, it helps to ensure a true WYSIWYG experience.');
975
  $form['acf']['allowed_content']['f']['#description'] = t('CKEditor will not filter any tags and as a result, the user will be able to insert any content into the editor. The content will only be filtered by server-side filters associated with input formats.');
976

    
977
  $form['acf']['extraAllowedContent'] = array(
978
    '#type' => 'textarea',
979
    '#title' => t('Extra allowed content'),
980
    '#default_value' => !empty($profile->settings['extraAllowedContent']) ? $profile->settings['extraAllowedContent'] : "",
981
    '#cols' => 60,
982
    '#rows' => 5,
983
    '#description' => t(
984
      'Set additional allowed content rules for CKEditor. Separate rules with a semicolon. See !docs for more information.', array(
985
        '!docs' => l(t('CKEditor documentation'), 'http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-allowedContent')
986
       )).'<p>'.
987
       t('<strong>Example:</strong> !rules', array(
988
         '!rules' => "<code>object[width,height];param[name,value];embed[*];</code>"
989
       )).'</p>',
990
    '#wysiwyg' => FALSE,
991
  );
992

    
993
  $form['output'] = array(
994
    '#type' => 'fieldset',
995
    '#title' => t('Cleanup and output'),
996
    '#collapsible' => TRUE,
997
    '#collapsed' => TRUE,
998
  );
999

    
1000
  $form['output']['enter_mode'] = array(
1001
    '#type' => 'select',
1002
    '#title' => t('Enter mode'),
1003
    '#default_value' => !empty($profile->settings['enter_mode']) ? $profile->settings['enter_mode'] : 'p',
1004
    '#options' => array(
1005
      'p' => '<p>',
1006
      'br' => '<br>',
1007
      'div' => '<div>'
1008
    ),
1009
    '#description' => t('Set which tag should be used by CKEditor when the <em>Enter</em> key is pressed.')
1010
  );
1011

    
1012
  $form['output']['shift_enter_mode'] = array(
1013
    '#type' => 'select',
1014
    '#title' => t('Shift+Enter mode'),
1015
    '#default_value' => !empty($profile->settings['shift_enter_mode']) ? $profile->settings['shift_enter_mode'] : 'br',
1016
    '#options' => array(
1017
      'p' => '<p>',
1018
      'br' => '<br>',
1019
      'div' => '<div>'
1020
    ),
1021
    '#description' => t('Set which tag should be used by CKEditor when the <em>Shift+Enter</em> key combination is pressed.')
1022
  );
1023

    
1024
  $form['output']['font_format'] = array(
1025
    '#type' => 'textfield',
1026
    '#title' => t('Font formats'),
1027
    '#default_value' => !empty($profile->settings['font_format']) ? $profile->settings['font_format'] : 'p;div;pre;address;h1;h2;h3;h4;h5;h6',
1028
    '#size' => 40,
1029
    '#maxlength' => 250,
1030
    '#description' => t(
1031
        'Semicolon-separated list of HTML font formats. Allowed values are: !allowed_values', array(
1032
      '!allowed_values' => '<code>p;div;pre;address;h1;h2;h3;h4;h5;h6</code>'
1033
        )
1034
    )
1035
  );
1036

    
1037
  if (!empty($profile->settings['formatting']['custom_formatting_options'])) {
1038
    foreach ($profile->settings['formatting']['custom_formatting_options'] as $k => $v) {
1039
      if ($v === 0) {
1040
        unset($profile->settings['formatting']['custom_formatting_options'][$k]);
1041
      }
1042
    }
1043
  }
1044

    
1045
  $form['output']['custom_formatting'] = array(
1046
    '#type' => 'radios',
1047
    '#title' => t('Use custom formatting options'),
1048
    '#default_value' => !empty($profile->settings['custom_formatting']) ? $profile->settings['custom_formatting'] : 'f',
1049
    '#options' => array(
1050
      't' => t('Yes'),
1051
      'f' => t('No'),
1052
    ),
1053
  );
1054

    
1055
  $form['output']['formatting'] = array(
1056
    '#type' => 'fieldset',
1057
    '#title' => t('Custom formatting options'),
1058
    '#tree' => TRUE,
1059
  );
1060

    
1061
  $form['output']['formatting']['custom_formatting_options'] = array(
1062
    '#type' => 'checkboxes',
1063
    '#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'),
1064
    '#options' => array(
1065
      'indent' => t('Indent the element contents.'),
1066
      'breakBeforeOpen' => t('Break line before the opening tag.'),
1067
      'breakAfterOpen' => t('Break line after the opening tag.'),
1068
      'breakBeforeClose' => t('Break line before the closing tag.'),
1069
      'breakAfterClose' => t('Break line after the closing tag.'),
1070
      'pre_indent' => t('Indent the <code>&lt;pre&gt;</code> element contents.'),
1071
    ),
1072
  );
1073

    
1074
  $form['css'] = array(
1075
    '#type' => 'fieldset',
1076
    '#title' => t('CSS'),
1077
    '#collapsible' => TRUE,
1078
    '#collapsed' => TRUE
1079
  );
1080

    
1081
  $current_theme = variable_get('theme_default', $theme);
1082
  $theme_path = drupal_get_path('theme', $current_theme);
1083

    
1084
  $form['css']['css_mode'] = array(
1085
    '#type' => 'select',
1086
    '#title' => t('Editor CSS'),
1087
    '#default_value' => !empty($profile->settings['css_mode']) ? $profile->settings['css_mode'] : 'theme',
1088
    '#options' => array(
1089
      'theme' => t('Use theme CSS'),
1090
      'self' => t('Define CSS'),
1091
      'none' => t('CKEditor default')
1092
    ),
1093
    '#description' => t(
1094
        '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.', array(
1095
      '!title_theme_css' => '<br /><strong>' . t('Use theme CSS') . '</strong>',
1096
      '!title_define_css' => '<br /><strong>' . t('Define CSS') . '</strong>',
1097
      '!title_ckeditor_default' => '<br /><strong>' . t('CKEditor default') . '</strong>',
1098
      '!style_css' => '<code>style.css</code>'
1099
        )
1100
    )
1101
  );
1102

    
1103
  $form['css']['css_path'] = array(
1104
    '#type' => 'textfield',
1105
    '#title' => t('CSS file path'),
1106
    '#default_value' => !empty($profile->settings['css_path']) ? $profile->settings['css_path'] : "",
1107
    '#size' => 40,
1108
    '#maxlength' => 255,
1109
    '#description' => t(
1110
        '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 !title_define_css option above.', array(
1111
      '!example1' => '<code>"css/editor.css"</code>',
1112
      '!example2' => '<code>"/themes/garland/style.css,http://example.com/style.css"</code>',
1113
      '!title_define_css' => '<strong>' . t('Define CSS') . '</strong>'
1114
        )
1115
    ) .
1116
    '<br />' .
1117
    t('Available placeholders:!h &ndash; host name (!host).!t &ndash; path to theme (!theme).', array(
1118
      '!h' => '<br /><code>%h</code>',
1119
      '!t' => '<br /><code>%t</code>',
1120
      '!host' => '<code>' . base_path() . '</code>',
1121
      '!theme' => '<code>' . base_path() . $theme_path . '/</code>'
1122
        )
1123
    )
1124
  );
1125

    
1126
  $form['css']['css_style'] = array(
1127
    '#type' => 'select',
1128
    '#title' => t('Predefined styles'),
1129
    '#default_value' => !empty($profile->settings['css_style']) ? $profile->settings['css_style'] : 'theme',
1130
    '#options' => array(
1131
      'theme' => t('Use theme ckeditor.styles.js'),
1132
      'self' => t('Define path to ckeditor.styles.js'),
1133
      'default' => t('CKEditor default')
1134
    ),
1135
    '#description' => t(
1136
        '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.', array(
1137
      '!ckeditor_styles_js_file' => '<code>ckeditor.styles.js</code>',
1138
      '!ckeditor_styles_js_path' => '<code>' . drupal_get_path('module', 'ckeditor') . '/ckeditor.styles.js</code>',
1139
      '!theme' => '<code>' . $theme_path . '/ckeditor.styles.js' . '</code>'
1140
        )
1141
    )
1142
  );
1143

    
1144
  $form['css']['styles_path'] = array(
1145
    '#type' => 'textfield',
1146
    '#title' => t('Predefined styles path'),
1147
    '#default_value' => !empty($profile->settings['styles_path']) ? $profile->settings['styles_path'] : "",
1148
    '#size' => 40,
1149
    '#maxlength' => 255,
1150
    '#description' => t(
1151
        'Enter the path to a file with predefined styles (Example: !example1). Make sure you select the !style_define_path option above.', array(
1152
      '!style_define_path' => '<strong>' . t('Define path to ckeditor.styles.js') . '</strong>',
1153
      '!ckeditor_styles_js_file' => '<code>ckeditor.styles.js</code>',
1154
      '!example1' => '<code>/ckeditor.styles.js</code>'
1155
        )
1156
    ) .
1157
    '<br />' .
1158
    t('Available placeholders:!h &ndash; host name (!host).!t &ndash; path to theme (!theme).!m &ndash; path to the CKEditor module (!module).', array(
1159
      '!h' => '<br /><code>%h</code>',
1160
      '!t' => '<br /><code>%t</code>',
1161
      '!m' => '<br /><code>%m</code>',
1162
      '!host' => '<code>' . base_path() . '</code>',
1163
      '!theme' => '<code>' . base_path() . $theme_path . '/</code>',
1164
      '!module' => '<code>' . drupal_get_path('module', 'ckeditor') . '</code>'
1165
        )
1166
    )
1167
  );
1168

    
1169
  $form['ckeditor_upload_settings'] = array(
1170
    '#type' => 'fieldset',
1171
    '#title' => t('File browser settings'),
1172
    '#collapsible' => TRUE,
1173
    '#collapsed' => TRUE,
1174
    '#description' => t(
1175
        '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 or !elfinder. CKEditor can be also integrated with !ckfinder, an advanced Ajax file manager.', array(
1176
      '!imce' => l(t('IMCE'), 'http://drupal.org/project/imce'),
1177
      '!elfinder' => l(t('elFinder'), 'http://drupal.org/project/elfinder'),
1178
      '!ckfinder' => l(t('CKFinder'), 'http://cksource.com/ckfinder')
1179
        )
1180
    )
1181
  );
1182

    
1183
  $filebrowsers = array(
1184
    'none' => t('None'),
1185
    'ckfinder' => t('CKFinder'),
1186
  );
1187

    
1188
  $filebrowsers_dialogs = array(
1189
    '' => t('Same as in the Link dialog window'),
1190
    'ckfinder' => t('CKFinder'),
1191
  );
1192

    
1193
  if (module_exists('imce')) {
1194
    $filebrowsers['imce'] = t('IMCE');
1195
    $filebrowsers_dialogs['imce'] = t('IMCE');
1196
  }
1197

    
1198
  if (module_exists('elfinder')) {
1199
    $filebrowsers['elfinder'] = t('elFinder');
1200
    $filebrowsers_dialogs['elfinder'] = t('elFinder');
1201
  }
1202

    
1203
  /* MODULES NOT PORTED TO D7
1204
    if (module_exists('tinybrowser')) {
1205
    $filebrowsers['tinybrowser'] = t('TinyBrowser');
1206
    $filebrowsers_dialogs['tinybrowser'] = t('TinyBrowser');
1207
    }
1208

    
1209
    if (module_exists('imagebrowser')) {
1210
    $filebrowsers['ib'] = t('Image Browser');
1211
    $filebrowsers_dialogs['ib'] = t('Image Browser');
1212
    }
1213

    
1214
    if (module_exists('webfm_popup')) {
1215
    $filebrowsers['webfm'] = t('Web File Manager');
1216
    $filebrowsers_dialogs['webfm'] = t('Web File Manager');
1217
    }
1218
   */
1219
  $form['ckeditor_upload_settings']['filebrowser'] = array(
1220
    '#type' => 'select',
1221
    '#title' => t('File browser type (Link dialog window)'),
1222
    '#default_value' => !empty($profile->settings['filebrowser']) ? $profile->settings['filebrowser'] : 'none',
1223
    '#options' => $filebrowsers,
1224
    '#description' => t('Select the file browser that you would like to use to upload files.'),
1225
  );
1226

    
1227
  $form['ckeditor_upload_settings']['filebrowser_image'] = array(
1228
    '#type' => 'select',
1229
    '#title' => t('File browser type (Image dialog window)'),
1230
    '#default_value' => !empty($profile->settings['filebrowser_image']) ? $profile->settings['filebrowser_image'] : 'none',
1231
    '#options' => $filebrowsers_dialogs,
1232
    '#description' => t('Select the file browser that you would like to use to upload images.'),
1233
  );
1234

    
1235
  $form['ckeditor_upload_settings']['filebrowser_flash'] = array(
1236
    '#type' => 'select',
1237
    '#title' => t('File browser type (Flash dialog window)'),
1238
    '#default_value' => !empty($profile->settings['filebrowser_flash']) ? $profile->settings['filebrowser_flash'] : 'none',
1239
    '#options' => $filebrowsers_dialogs,
1240
    '#description' => t('Select the file browser that you would like to use to upload Flash movies.'),
1241
  );
1242

    
1243
  if (variable_get('file_default_scheme', '') != 'private') {
1244
    $current_user_files_path = empty($profile->settings['UserFilesPath']) ? "%b%f/" : $profile->settings['UserFilesPath'];
1245
    $current_user_files_path = strtr($current_user_files_path, array("%f" => variable_get('file_public_path', conf_path() . '/files'), "%u" => "UID", "%b" => base_path(), "%n" => "UNAME"));
1246

    
1247
    $current_user_files_absolute_path = empty($profile->settings['UserFilesAbsolutePath']) ? "%d%b%f/" : $profile->settings['UserFilesAbsolutePath'];
1248
    $current_user_files_absolute_path = strtr($current_user_files_absolute_path, array("%f" => variable_get('file_public_path', conf_path() . '/files'), "%u" => "UID", "%b" => base_path(), "%d" => ckeditor_get_document_root_full_path(), "%n" => "UNAME"));
1249

    
1250

    
1251
    $form['ckeditor_upload_settings']['UserFilesPath'] = array(
1252
      '#type' => 'textfield',
1253
      '#prefix' => '<fieldset><legend>' . t('CKFinder settings') . '</legend>',
1254
      '#title' => t('Path to uploaded files'),
1255
      '#default_value' => !empty($profile->settings['UserFilesPath']) ? $profile->settings['UserFilesPath'] : "%b%f/",
1256
      '#size' => 40,
1257
      '#maxlength' => 255,
1258
      '#description' => t('Path to uploaded files relative to the document root.') .
1259
      '<br />' .
1260
      t('Available placeholders:!b &ndash; the base URL path of the Drupal installation (!base).!f &ndash; the Drupal file system path where the files are stored (!files).!u &ndash; User ID.!n &ndash; Username.', array(
1261
        '!n' => '<br /><code>%n</code>',
1262
        '!u' => '<br /><code>%u</code>',
1263
        '!f' => '<br/><code>%f</code>',
1264
        '!b' => '<br/><code>%b</code>',
1265
        '!files' => '<code>' . variable_get('file_public_path', conf_path() . '/files') . '</code>',
1266
        '!base' => '<code>' . base_path() . '</code>'
1267
          )
1268
      ) .
1269
      '<br />' .
1270
      t('Current path: !path', array(
1271
        '!path' => '<code>' . $current_user_files_path . '</code>'
1272
          )
1273
      )
1274
    );
1275

    
1276
    $form['ckeditor_upload_settings']['UserFilesAbsolutePath'] = array(
1277
      '#type' => 'textfield',
1278
      '#title' => t('Absolute path to uploaded files'),
1279
      '#default_value' => !empty($profile->settings['UserFilesAbsolutePath']) ? $profile->settings['UserFilesAbsolutePath'] : "%d%b%f/",
1280
      '#size' => 40,
1281
      '#maxlength' => 255,
1282
      '#suffix' => '</fieldset>',
1283
      '#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.') .
1284
      '<br />' .
1285
      t('Available placeholders:!d &ndash; the server path to the document root (!root).!b &ndash; the base URL path of the Drupal installation (!base).!f &ndash; the Drupal file system path where the files are stored (!files).!u &ndash; User ID.!n &ndash; Username.', array(
1286
        '!u' => '<br /><code>%u</code>',
1287
        '!n' => '<br /><code>%n</code>',
1288
        '!d' => '<br/><code>%d</code>',
1289
        '!b' => '<br /><code>%b</code>',
1290
        '!f' => '<br/><code>%f</code>',
1291
        '!files' => '<code>' . variable_get('file_public_path', conf_path() . '/files') . '</code>',
1292
        '!base' => '<code>' . base_path() . '</code>',
1293
        '!root' => '<code>' . ckeditor_get_document_root_full_path() . '</code>'
1294
          )
1295
      ) .
1296
      '<br />' .
1297
      t('Current path: !path', array(
1298
        '!path' => '<code>' . $current_user_files_absolute_path . '</code>'
1299
          )
1300
      )
1301
    );
1302
  }
1303
  if (variable_get('file_default_scheme', '') == 'private') {
1304
    $form['ckeditor_upload_settings']['private_path_descrption'] = array(
1305
      '#markup' => '<div>' . t(
1306
          '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>.', array(
1307
        '!url' => l(t('CKEditor Global Profile'), 'admin/config/content/ckeditor/editg')
1308
          )
1309
      ) . '</div>',
1310
    );
1311
  }
1312

    
1313
  $form['advanced'] = array(
1314
    '#type' => 'fieldset',
1315
    '#title' => t('Advanced options'),
1316
    '#collapsible' => TRUE,
1317
    '#collapsed' => TRUE,
1318
  );
1319
  if (ckeditor_get_version(TRUE) == 3) {
1320
    $form['advanced']['ckeditor_load_method'] = array(
1321
      '#type' => 'select',
1322
      '#title' => t('Loading method'),
1323
      '#default_value' => !empty($profile->settings['ckeditor_load_method']) ? $profile->settings['ckeditor_load_method'] : 'ckeditor.js',
1324
      '#options' => _ckeditor_load_methods(),
1325
      '#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.', array(
1326
        '!ckeditor_basic_js' => '<code>ckeditor_basic.js</code>'
1327
          )
1328
      )
1329
    );
1330
    $form['advanced']['ckeditor_load_time_out'] = array(
1331
      '#type' => 'textfield',
1332
      '#title' => t('Loading timeout'),
1333
      '#default_value' => !empty($profile->settings['ckeditor_load_time_out']) ? $profile->settings['ckeditor_load_time_out'] : "0",
1334
      '#size' => 40,
1335
      '#maxlength' => 255,
1336
      '#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.', array(
1337
        '!ckeditor_basic_js' => '<code>ckeditor_basic.js</code>'
1338
          )
1339
      )
1340
    );
1341
  }
1342

    
1343
  $form['advanced']['forcePasteAsPlainText'] = array(
1344
    '#type' => 'select',
1345
    '#title' => t('Force pasting as plain text'),
1346
    '#default_value' => !empty($profile->settings['forcePasteAsPlainText']) ? $profile->settings['forcePasteAsPlainText'] : "f",
1347
    '#options' => array(
1348
      't' => t('Enabled'),
1349
      'f' => t('Disabled')
1350
    ),
1351
    '#description' => t('If enabled, HTML content will be automatically changed to plain text when pasting.'),
1352
  );
1353
  $form['advanced']['html_entities'] = array(
1354
    '#type' => 'radios',
1355
    '#title' => t('HTML Entities'),
1356
    '#default_value' => !empty($profile->settings['html_entities']) ? $profile->settings['html_entities'] : 'f',
1357
    '#description' => t('Convert all applicable characters to HTML entities.'),
1358
    '#options' => array(
1359
      'f' => t('No'),
1360
      't' => t('Yes')
1361
    ),
1362
  );
1363
  $form['advanced']['scayt_autoStartup'] = array(
1364
    '#type' => 'radios',
1365
    '#title' => t('Spellchecker'),
1366
    '#default_value' => !empty($profile->settings['scayt_autoStartup']) ? $profile->settings['scayt_autoStartup'] : 'f',
1367
    '#description' => t('If enabled, turns on SCAYT (Spell Check As You Type) automatically after loading the editor.'),
1368
    '#options' => array(
1369
      'f' => t('No'),
1370
      't' => t('Yes')
1371
    ),
1372
  );
1373
  $form['advanced']['theme_config_js'] = array(
1374
    '#type' => 'radios',
1375
    '#title' => t('Load !ckeditor_config_js from the theme path', array(
1376
      '!ckeditor_config_js' => '<code>ckeditor.config.js</code>'
1377
        )
1378
    ),
1379
    '#default_value' => !empty($profile->settings['theme_config_js']) ? $profile->settings['theme_config_js'] : 'f',
1380
    '#options' => array(
1381
      't' => t('Yes'),
1382
      'f' => t('No')
1383
    ),
1384
    '#description' => t('When enabled, the editor will try to load the !ckeditor_config_js file from the theme directory.', array(
1385
      '!ckeditor_config_js' => '<code>ckeditor.config.js</code>'
1386
        )
1387
    )
1388
  );
1389
  $form['advanced']['js_conf'] = array(
1390
    '#type' => 'textarea',
1391
    '#title' => t('Custom JavaScript configuration'),
1392
    '#default_value' => !empty($profile->settings['js_conf']) ? $profile->settings['js_conf'] : "",
1393
    '#cols' => 60,
1394
    '#rows' => 5,
1395
    '#description' => t(
1396
        '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.', array(
1397
      '!ckeditor_config' => '<code>' . drupal_get_path('module', 'ckeditor') . "/ckeditor.config.js</code>",
1398
      '!docs' => l(t('CKEditor documentation'), 'http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html'),
1399
      '@code' => "config.font_names = 'Arial;Times New Roman;Verdana';\nconfig.fontSize_sizes = '16/16px;24/24px;48/48px;';"
1400
        )
1401
    ),
1402
    '#wysiwyg' => FALSE,
1403
  );
1404

    
1405
  $form['submit'] = array(
1406
    '#type' => 'submit',
1407
    '#value' => t('Save')
1408
  );
1409

    
1410
  return $form;
1411
}
1412

    
1413
/**
1414
 * Form validation for a profile.
1415
 */
1416
function ckeditor_admin_profile_form_validate($form, &$form_state) {
1417
  $edit = & $form_state['values'];
1418
  /*
1419
    if ($edit['default'] == 't' && $edit['popup'] == 't') {
1420
    form_set_error('popup', t('If CKEditor is enabled by default, the popup window must be disabled.'));
1421
    }
1422

    
1423
    if ($edit['show_toggle'] == 't' && $edit['popup'] == 't') {
1424
    form_set_error('popup', t('If toggle is enabled, the popup window must be disabled.'));
1425
    }
1426
   */
1427
  if (!$edit['name']) {
1428
    form_set_error('name', t('You must give a profile name.'));
1429
  }
1430
  elseif (!preg_match('/^[A-Za-z0-9_]+$/', $edit['name'])) {
1431
    form_set_error('name', t('Enter a valid profile name. Only alphanumeric and underscore characters are allowed.'));
1432
  }
1433
  elseif ($edit['name'] == 'CKEditor Global Profile') {
1434
    form_set_error('name', t('This profile name is reserved. Please choose a different name.'));
1435
  }
1436
  elseif (!isset($edit['_profile']) || ($edit['_profile']->name != $edit['name'])) {
1437
    $result = ckeditor_profile_load($edit['name']);
1438
    if (!empty($result)) {
1439
      form_set_error('name', t('The profile name must be unique. A profile with this name already exists.'));
1440
    }
1441
  }
1442

    
1443
  if (!preg_match('/^\d+%?$/', $edit['width'])) {
1444
    form_set_error('width', t('Enter a valid width value. Examples: 400, 100%.'));
1445
  }
1446

    
1447
  if (!empty($edit['css_path'])) {
1448
    if ($edit['css_mode'] != 'self') {
1449
      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.'));
1450
    }
1451
    elseif (FALSE !== strpos($edit['css_path'], '"')) {
1452
      form_set_error('css_path', t('Double quotes are not allowed in the CSS path.'));
1453
    }
1454
    elseif (substr($edit['css_path'], 0, 1) == "'" && substr($edit['css_path'], -1) == "'") {
1455
      form_set_error('css_path', t('Enter a valid CSS path, do not surround it with quotes.'));
1456
    }
1457
  }
1458

    
1459
  if (!empty($edit['styles_path'])) {
1460
    if ($edit['css_style'] != 'self') {
1461
      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.'));
1462
    }
1463
    elseif (FALSE !== strpos($edit['styles_path'], '"')) {
1464
      form_set_error('styles_path', t('Double quotes are not allowed in the styles path.'));
1465
    }
1466
    elseif (substr($edit['styles_path'], 0, 1) == "'" && substr($edit['styles_path'], -1) == "'") {
1467
      form_set_error('styles_path', t('Enter a valid styles path, do not surround it with quotes.'));
1468
    }
1469
  }
1470

    
1471
  if (!empty($edit['font_format'])) {
1472
    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'])) {
1473
      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).'));
1474
    }
1475
  }
1476
  // @todo DOWNLOAD API
1477
  if (!empty($edit['UserFilesAbsolutePath']) && empty($edit['UserFilesPath'])) {
1478
    form_set_error('UserFilesPath', t('The path to uploaded files is required.'));
1479
  }
1480
  if (!empty($edit['UserFilesPath']) && empty($edit['UserFilesAbsolutePath'])) {
1481
    form_set_error('UserFilesPath', t('An absolute path to uploaded files is required.'));
1482
  }
1483

    
1484
  if (ckeditor_get_version(TRUE) == 3) {
1485
    $load_methods = _ckeditor_load_methods();
1486
    if (!isset($load_methods[$edit['ckeditor_load_method']])) {
1487
      form_set_error('ckeditor_load_method', t('Set a valid loading method.'));
1488
    }
1489
    if (!preg_match('#\d+#', $edit['ckeditor_load_time_out'])) {
1490
      form_set_error('ckeditor_load_time_out', t('Enter a valid loading timeout in seconds.'));
1491
    }
1492
  }
1493
  $toolbar = $edit['toolbar'];
1494
  $toolbar = str_replace("'", '"', $toolbar);
1495
  $toolbar = preg_replace('/(\w*)\s*\:/', '"${1}":', $toolbar);
1496

    
1497
  if (strpos($toolbar, 'CodeSnippet') !== false && empty($edit['loadPlugins']['codesnippet'])) {
1498
    form_set_error('loadPlugins][codesnippet', t('The Code Snippet plugin must be enabled if the CodeSnippet button is enabled in the toolbar.'));
1499
  }
1500
  if (strpos($toolbar, 'Mathjax') !== false && empty($edit['loadPlugins']['mathjax'])) {
1501
    form_set_error('loadPlugins][mathjax', t('The Mathjax plugin must be enabled if the Mathjax button is enabled in the toolbar.'));
1502
  }
1503
  if (!json_decode($toolbar)) {
1504
    form_set_error('toolbar', t('Enter a valid toolbar configuration.'));
1505
  }
1506
}
1507

    
1508
/**
1509
 * Form submit for a profile
1510
 */
1511
function ckeditor_admin_profile_form_submit($form, &$form_state) {
1512
  $edit = & $form_state['values'];
1513

    
1514
  if (isset($edit['_profile'])) {
1515
    ckeditor_profile_delete($edit['_profile']->name);
1516
    drupal_set_message(t('Your CKEditor profile was updated.'));
1517
  }
1518
  else {
1519
    drupal_set_message(t('Your CKEditor profile was created.'));
1520
  }
1521

    
1522
  $settings = ckeditor_admin_values_to_settings($edit);
1523
  db_insert('ckeditor_settings')
1524
      ->fields(array(
1525
        "name" => $edit['name'],
1526
        "settings" => $settings
1527
      ))
1528
      ->execute();
1529

    
1530
  if (!empty($edit['input_formats'])) {
1531
    foreach (array_keys($edit['input_formats']) as $format) {
1532
      if ($edit['input_formats'][$format] != '0') {
1533
        db_insert('ckeditor_input_format')->fields(array("name" => $edit['name'], "format" => $format))->execute();
1534
      }
1535
    }
1536
  }
1537

    
1538
  $form_state['redirect'] = 'admin/config/content/ckeditor';
1539
}
1540

    
1541
/**
1542
 * Form builder for a clone profile
1543
 */
1544
function ckeditor_admin_profile_clone_form($form, $form_state, $task, $oldprofile) {
1545
  return ckeditor_admin_profile_form($form, $form_state, $task, $oldprofile);
1546
}
1547

    
1548
/**
1549
 * Form validation for a clone profile
1550
 */
1551
function ckeditor_admin_profile_clone_form_validate($form_state, $oldprofile) {
1552
  ckeditor_admin_profile_form_validate($form_state, $oldprofile);
1553
}
1554

    
1555
/**
1556
 * Form submit for a clone profile
1557
 */
1558
function ckeditor_admin_profile_clone_form_submit($form, &$form_state) {
1559
  $edit = & $form_state['values'];
1560
  drupal_set_message(t('Your CKEditor profile was created.'));
1561
  $settings = ckeditor_admin_values_to_settings($edit);
1562
  db_insert('ckeditor_settings')
1563
      ->fields(array(
1564
        "name" => $edit['name'],
1565
        "settings" => $settings
1566
      ))
1567
      ->execute();
1568

    
1569
  if (!empty($edit['input_formats'])) {
1570
    foreach (array_keys($edit['input_formats']) as $format) {
1571
      if ($edit['input_formats'][$format] != 0) {
1572
        db_insert('ckeditor_input_format')->fields(array("name" => $edit['name'], "format" => $format))->execute();
1573
      }
1574
    }
1575
  }
1576

    
1577
  $form_state['redirect'] = 'admin/config/content/ckeditor';
1578
}
1579

    
1580
/**
1581
 * Form builder for a profile delete
1582
 */
1583
function ckeditor_admin_profile_delete_form($form, $form_state, $profile) {
1584
  $form = array();
1585

    
1586
  $form['_profile'] = array(
1587
    '#type' => 'value',
1588
    '#value' => $profile,
1589
  );
1590

    
1591
  $form['question'] = array(
1592
    '#type' => 'item',
1593
    '#markup' => t(
1594
        'Are you sure that you want to delete the CKEditor profile <strong>%profile</strong>?', array(
1595
      '%profile' => $profile->name
1596
        )
1597
    ),
1598
  );
1599

    
1600
  $form['delete'] = array(
1601
    '#type' => 'submit',
1602
    '#id' => 'delete',
1603
    '#value' => t('Delete'),
1604
  );
1605

    
1606
  $form['back'] = array(
1607
    '#type' => 'submit',
1608
    '#id' => 'back',
1609
    '#value' => t('Cancel'),
1610
  );
1611

    
1612
  return $form;
1613
}
1614

    
1615
/**
1616
 * Submit form for a profile delete
1617
 */
1618
function ckeditor_admin_profile_delete_form_submit($form, &$form_state) {
1619
  $v = & $form_state['values'];
1620

    
1621
  if ($form_state['clicked_button']['#id'] == 'delete') {
1622
    ckeditor_profile_delete($v['_profile']->name);
1623
    drupal_set_message(t('The CKEditor profile was deleted.'));
1624
  }
1625

    
1626
  $form_state['redirect'] = 'admin/config/content/ckeditor';
1627
}
1628

    
1629
/**
1630
 * Converts an array of form values to a serialized array that does not
1631
 * contain Drupal Form API values
1632
 */
1633
function ckeditor_admin_values_to_settings($values) {
1634
  $plugins = array();
1635
  if (isset($values['loadPlugins'])) {
1636
    $plugins = $values['loadPlugins'];
1637
  }
1638
  unset($values['name'], $values['input_formats'], $values['_profile'], $values['op'], $values['submit'], $values['form_build_id'], $values['form_token'], $values['form_id'], $values['loadPlugins']);
1639

    
1640
  // Replace CRLF with LF in toolbar settings
1641
  if(isset($values['toolbar'])){
1642
    $values['toolbar'] = str_replace("\r\n", "\n", $values['toolbar']);
1643
  }
1644

    
1645
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
1646
  $plugin_list = ckeditor_load_plugins();
1647
  $values['loadPlugins'] = array();
1648
  if (!empty($plugins)) {
1649
    foreach (array_keys($plugins) as $plugin) {
1650
      if ($plugins[$plugin] != '0') {
1651
        $values['loadPlugins'][$plugin] = $plugin_list[$plugin];
1652
      }
1653
    }
1654
  }
1655

    
1656
  return serialize($values);
1657
}
1658

    
1659
/**
1660
 * Remove a profile from the database.
1661
 */
1662
function ckeditor_profile_delete($name) {
1663
  db_delete('ckeditor_settings')
1664
      ->condition('name', $name)
1665
      ->execute();
1666
  db_delete('ckeditor_input_format')
1667
      ->condition('name', $name)
1668
      ->execute();
1669
}
1670

    
1671
/*
1672
 * List of CKEditor librares to load
1673
 */
1674

    
1675
function _ckeditor_load_methods() {
1676
  $result = array('ckeditor.js' => 'ckeditor.js');
1677
  $ckeditor_local_path = ckeditor_path('local');
1678
  if ($ckeditor_local_path == '<URL>') {
1679
    return $result;
1680
  }
1681
  if (file_exists($ckeditor_local_path . '/ckeditor_basic.js')) {
1682
    $result['ckeditor_basic.js'] = 'ckeditor_basic.js';
1683
  }
1684
  if (file_exists($ckeditor_local_path . '/ckeditor_source.js')) {
1685
    $result['ckeditor_source.js'] = 'ckeditor_source.js (' . t('for developers only') . ')';
1686
  }
1687
  return $result;
1688
}
1689

    
1690
/*
1691
 * Disable WYSIWYG module
1692
 */
1693

    
1694
function ckeditor_disable_wysiwyg($token) {
1695
  if (!drupal_valid_token($token, 'ckeditorDisableWysiwyg')) {
1696
    exit();
1697
  }
1698
  module_disable(array('wysiwyg'));
1699
  drupal_set_message(t('The WYSIWYG module is disabled.'));
1700

    
1701
  drupal_goto('admin/config/content/ckeditor');
1702
}
1703

    
1704
/*
1705
 * Get all available toolbar buttons
1706
 */
1707

    
1708
function ckeditor_toolbar_buttons_all() {
1709
  $path = base_path() . drupal_get_path('module', 'ckeditor');
1710

    
1711
  //CKEditor default buttons
1712
  $buttons = array(
1713
    'Source' => array('name' => 'Source', 'icon' => $path . '/images/buttons/source.png', 'title' => 'Source', 'row' => 1),
1714
    'Save' => array('name' => 'Save', 'icon' => $path . '/images/buttons/save.png', 'title' => 'Save', 'row' => 1),
1715
    'NewPage' => array('name' => 'NewPage', 'icon' => $path . '/images/buttons/newpage.png', 'title' => 'New Page', 'row' => 1),
1716
    'Preview' => array('name' => 'Preview', 'icon' => $path . '/images/buttons/preview.png', 'title' => 'Preview', 'row' => 1),
1717
    'Templates' => array('name' => 'Templates', 'icon' => $path . '/images/buttons/templates.png', 'title' => 'Templates', 'row' => 1),
1718
    'Cut' => array('name' => 'Cut', 'icon' => $path . '/images/buttons/cut.png', 'title' => 'Cut', 'row' => 1),
1719
    'Copy' => array('name' => 'Copy', 'icon' => $path . '/images/buttons/copy.png', 'title' => 'Copy', 'row' => 1),
1720
    'Paste' => array('name' => 'Paste', 'icon' => $path . '/images/buttons/paste.png', 'title' => 'Paste', 'row' => 1),
1721
    'PasteText' => array('name' => 'PasteText', 'icon' => $path . '/images/buttons/pastetext.png', 'title' => 'Paste as plain text', 'row' => 1),
1722
    'PasteFromWord' => array('name' => 'PasteFromWord', 'icon' => $path . '/images/buttons/pastefromword.png', 'title' => 'Paste from Word', 'row' => 1),
1723
    'Print' => array('name' => 'Print', 'icon' => $path . '/images/buttons/print.png', 'title' => 'Print', 'row' => 1),
1724
    'SpellChecker' => array('name' => 'SpellChecker', 'icon' => $path . '/images/buttons/spellchecker.png', 'title' => 'Check Spelling', 'row' => 1),
1725
    'Scayt' => array('name' => 'Scayt', 'icon' => $path . '/images/buttons/scayt.png', 'title' => 'Spell Check As you Type', 'row' => 1), //TODO sprawdzic ta opcje
1726
    'Undo' => array('name' => 'Undo', 'icon' => $path . '/images/buttons/undo.png', 'title' => 'Undo', 'row' => 1),
1727
    'Redo' => array('name' => 'Redo', 'icon' => $path . '/images/buttons/redo.png', 'title' => 'Redo', 'row' => 1),
1728
    'Find' => array('name' => 'Find', 'icon' => $path . '/images/buttons/find.png', 'title' => 'Find', 'row' => 1),
1729
    'Replace' => array('name' => 'Replace', 'icon' => $path . '/images/buttons/replace.png', 'title' => 'Replace', 'row' => 1),
1730
    'SelectAll' => array('name' => 'SelectAll', 'icon' => $path . '/images/buttons/selectall.png', 'title' => 'Select All', 'row' => 1),
1731
    'RemoveFormat' => array('name' => 'RemoveFormat', 'icon' => $path . '/images/buttons/removeformat.png', 'title' => 'Remove Format', 'row' => 1),
1732
    'Form' => array('name' => 'Form', 'icon' => $path . '/images/buttons/form.png', 'title' => 'Form', 'row' => 1),
1733
    'Checkbox' => array('name' => 'Checkbox', 'icon' => $path . '/images/buttons/checkbox.png', 'title' => 'Checkbox', 'row' => 1),
1734
    'Radio' => array('name' => 'Radio', 'icon' => $path . '/images/buttons/radio.png', 'title' => 'Radio Button', 'row' => 1),
1735
    'TextField' => array('name' => 'TextField', 'icon' => $path . '/images/buttons/textfield.png', 'title' => 'Text Field', 'row' => 1),
1736
    'Textarea' => array('name' => 'Textarea', 'icon' => $path . '/images/buttons/textarea.png', 'title' => 'Textarea', 'row' => 1),
1737
    'Select' => array('name' => 'Select', 'icon' => $path . '/images/buttons/select.png', 'title' => 'Selection Field', 'row' => 1),
1738
    'Button' => array('name' => 'Button', 'icon' => $path . '/images/buttons/button.png', 'title' => 'Button', 'row' => 1),
1739
    'ImageButton' => array('name' => 'ImageButton', 'icon' => $path . '/images/buttons/imagebutton.png', 'title' => 'Image Button', 'row' => 1),
1740
    'HiddenField' => array('name' => 'HiddenField', 'icon' => $path . '/images/buttons/hiddenfield.png', 'title' => 'Hidden Field', 'row' => 1),
1741
    'Bold' => array('name' => 'Bold', 'icon' => $path . '/images/buttons/bold.png', 'title' => 'Bold', 'row' => 2),
1742
    'Italic' => array('name' => 'Italic', 'icon' => $path . '/images/buttons/italic.png', 'type' => 'command', 'title' => 'Italic', 'row' => 2),
1743
    'Underline' => array('name' => 'Underline', 'icon' => $path . '/images/buttons/underline.png', 'title' => 'Underline', 'row' => 2),
1744
    'Strike' => array('name' => 'Strike', 'icon' => $path . '/images/buttons/strike.png', 'title' => 'Strike Through', 'row' => 2),
1745
    'Subscript' => array('name' => 'Subscript', 'icon' => $path . '/images/buttons/subscript.png', 'title' => 'Subscript', 'row' => 2),
1746
    'Superscript' => array('name' => 'Superscript', 'icon' => $path . '/images/buttons/superscript.png', 'title' => 'Superscript', 'row' => 2),
1747
    'NumberedList' => array('name' => 'NumberedList', 'icon' => $path . '/images/buttons/numberedlist.png', 'title' => 'Insert/Remove Numbered List', 'row' => 2),
1748
    'BulletedList' => array('name' => 'BulletedList', 'icon' => $path . '/images/buttons/bulletedlist.png', 'title' => 'Insert/Remove Bulleted List', 'row' => 2),
1749
    'Outdent' => array('name' => 'Outdent', 'icon' => $path . '/images/buttons/outdent.png', 'title' => 'Decrease Indent', 'row' => 2),
1750
    'Indent' => array('name' => 'Indent', 'icon' => $path . '/images/buttons/indent.png', 'title' => 'Increase Indent', 'row' => 2),
1751
    'Blockquote' => array('name' => 'Blockquote', 'icon' => $path . '/images/buttons/blockquote.png', 'title' => 'Block Quote', 'row' => 2),
1752
    'CreateDiv' => array('name' => 'CreateDiv', 'icon' => $path . '/images/buttons/creatediv.png', 'title' => 'Create Div Container', 'row' => 2),
1753
    'JustifyLeft' => array('name' => 'JustifyLeft', 'icon' => $path . '/images/buttons/justifyleft.png', 'title' => 'Left Justify', 'row' => 2),
1754
    'JustifyCenter' => array('name' => 'JustifyCenter', 'icon' => $path . '/images/buttons/justifycenter.png', 'title' => 'Center Justify', 'row' => 2),
1755
    'JustifyRight' => array('name' => 'JustifyRight', 'icon' => $path . '/images/buttons/justifyright.png', 'title' => 'Right Justify', 'row' => 2),
1756
    'JustifyBlock' => array('name' => 'JustifyBlock', 'icon' => $path . '/images/buttons/justifyblock.png', 'title' => 'Block Justify', 'row' => 2),
1757
    'BidiLtr' => array('name' => 'BidiLtr', 'icon' => $path . '/images/buttons/bidiltr.png', 'title' => 'Text direction from left to right', 'row' => 2),
1758
    'BidiRtl' => array('name' => 'BidiRtl', 'icon' => $path . '/images/buttons/bidirtl.png', 'title' => 'Text direction from right to left', 'row' => 2),
1759
    'Language' => array('name' => 'Language', 'icon' => $path . '/images/buttons/language.png', 'title' => 'Set Language', 'row' => 2),
1760
    'Link' => array('name' => 'Link', 'icon' => $path . '/images/buttons/link.png', 'title' => 'Link', 'row' => 2),
1761
    'Unlink' => array('name' => 'Unlink', 'icon' => $path . '/images/buttons/unlink.png', 'title' => 'Unlink', 'row' => 2),
1762
    'Anchor' => array('name' => 'Anchor', 'icon' => $path . '/images/buttons/anchor.png', 'title' => 'Anchor', 'row' => 2),
1763
    'Image' => array('name' => 'Image', 'icon' => $path . '/images/buttons/image.png', 'title' => 'Image', 'row' => 2),
1764
    'Flash' => array('name' => 'Flash', 'icon' => $path . '/images/buttons/flash.png', 'title' => 'Flash', 'row' => 2),
1765
    'Table' => array('name' => 'Table', 'icon' => $path . '/images/buttons/table.png', 'title' => 'Table', 'row' => 2),
1766
    'HorizontalRule' => array('name' => 'HorizontalRule', 'icon' => $path . '/images/buttons/horizontalrule.png', 'title' => 'Insert Horizontal Line', 'row' => 2),
1767
    'Smiley' => array('name' => 'Smiley', 'icon' => $path . '/images/buttons/smiley.png', 'title' => 'Smiley', 'row' => 2),
1768
    'SpecialChar' => array('name' => 'SpecialChar', 'icon' => $path . '/images/buttons/specialchar.png', 'title' => 'Insert Special Character', 'row' => 2),
1769
    'PageBreak' => array('name' => 'PageBreak', 'icon' => $path . '/images/buttons/pagebreak.png', 'title' => 'Insert Page Break for Printing', 'row' => 2),
1770
    'Styles' => array('name' => 'Styles', 'icon' => $path . '/images/buttons/styles.png', 'title' => 'Formatting Styles', 'row' => 3),
1771
    'Format' => array('name' => 'Format', 'icon' => $path . '/images/buttons/format.png', 'title' => 'Paragraph Format', 'row' => 3),
1772
    'Font' => array('name' => 'Font', 'icon' => $path . '/images/buttons/font.png', 'title' => 'Font Name', 'row' => 3),
1773
    'FontSize' => array('name' => 'FontSize', 'icon' => $path . '/images/buttons/size.png', 'title' => 'Font Size', 'row' => 3),
1774
    'TextColor' => array('name' => 'TextColor', 'icon' => $path . '/images/buttons/textcolor.png', 'title' => 'Text Color', 'row' => 3),
1775
    'BGColor' => array('name' => 'BGColor', 'icon' => $path . '/images/buttons/bgcolor.png', 'title' => 'Background Color', 'row' => 3),
1776
    'Maximize' => array('name' => 'Maximize', 'icon' => $path . '/images/buttons/maximize.png', 'title' => 'Maximize', 'row' => 3),
1777
    'ShowBlocks' => array('name' => 'ShowBlocks', 'icon' => $path . '/images/buttons/showblocks.png', 'title' => 'Show Blocks', 'row' => 3),
1778
    'Iframe' => array('name' => 'Iframe', 'icon' => $path . '/images/buttons/iframe.png', 'title' => 'IFrame', 'row' => 3),
1779
    'About' => array('name' => 'About', 'icon' => $path . '/images/buttons/about.png', 'title' => 'About', 'row' => 3),
1780
    '__spacer' => array('name' => FALSE, 'icon' => $path . '/images/buttons/spacer.png', 'title' => 'Spacer', 'row' => 4),
1781
    '__group' => array('name' => FALSE, 'icon' => $path . '/images/buttons/group.png', 'title' => 'Group', 'row' => 4)
1782
  );
1783

    
1784
  $plugins = ckeditor_load_plugins(TRUE);
1785
  foreach ($plugins as $plugin_name => $plugin) {
1786
    if (!isset($plugin['buttons']) || $plugin['buttons'] == FALSE)
1787
      continue;
1788
    foreach ((array) $plugin['buttons'] as $button_name => $button) {
1789
      $buttons[$button_name] = array('name' => $button_name, 'icon' => $plugin['path'] . $button['icon'], 'title' => t($button['label']), 'row' => 4);
1790
    }
1791
  }
1792

    
1793
  return $buttons;
1794
}
1795

    
1796
/**
1797
 * Add security filters to the configuration panel available in the CKEditor profile administration section
1798
 */
1799
function _ckeditor_admin_profile_form_security_filters(&$form, $profile, $security_filters) {
1800
  foreach ((array) $security_filters['modules'] as $module_name => $module_conf) {
1801
    if (isset($module_conf['project_page']) && strlen($module_conf['project_page']) > 0) {
1802
      $form['security']['filters'][$module_name] = array(
1803
        '#type' => 'fieldset',
1804
        '#title' => t(
1805
            "!title <a href=\"!link\" target=\"_blank\">project page</a>", array(
1806
          "!title" => $module_conf['title'],
1807
          "!link" => $module_conf['project_page']
1808
            )
1809
        ),
1810
        '#weight' => $module_conf['weight']
1811
      );
1812
    }
1813
    else {
1814
      $form['security']['filters'][$module_name] = array(
1815
        '#type' => 'fieldset',
1816
        '#title' => t("!title", array("!title" => $module_conf['title'])),
1817
        '#weight' => $module_conf['weight']
1818
      );
1819
    }
1820

    
1821
    if ($module_conf['installed'] == TRUE) {
1822
      foreach ((array) $module_conf['filters'] as $filter_name => $filter_conf) {
1823
        $filter_text_formats = '<div class="filter-text-formats" filter="' . $filter_name . '"></div><div class="filter-info">';
1824
        $form['security']['filters'][$module_name][$filter_name] = array(
1825
          '#type' => 'item',
1826
          '#title' => t("@data", array('@data' => $filter_conf['title'])),
1827
          '#description' => t("!data", array('!data' => $filter_conf['description'])),
1828
          '#prefix' => "<div class=\"filter-wrapper\"></div>" . $filter_text_formats,
1829
          '#suffix' => "</div>"
1830
        );
1831
      }
1832
    }
1833
    else {
1834
      $form['security']['filters'][$module_name]['not_installed'] = array(
1835
        '#markup' => t("<i>Not installed</i>")
1836
      );
1837
    }
1838
  }
1839
}
1840

    
1841
function ckeditor_skinframe() {
1842
  header('Content-Type: text/html; charset=utf-8');
1843

    
1844
  if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], 'ckeditorSkinframeCall')) {
1845
    exit;
1846
  }
1847

    
1848
  $editor_path = ckeditor_path('relative');
1849
  if ($editor_path == '<URL>')
1850
    $editor_path = ckeditor_path('url');
1851
  $module_drupal_path = ckeditor_module_path('relative');
1852

    
1853
  $html = "<!DOCTYPE html>";
1854
  $html .= "<html>";
1855
  $html .= "<head>";
1856
  $html .= '<title>CKEditor UI Color Picker</title>';
1857
  $html .= "<script type=\"text/javascript\" src=\"{$editor_path}/ckeditor.js\"></script>";
1858
  $html .= "</head>";
1859
  $html .= "<body>";
1860
  $html .= "<input type=\"hidden\" name=\"uicolor_user\"/>";
1861
  $html .= "<div id=\"editor\" style=\"height: 200px;\">Click the <strong>UI Color Picker</strong> button to set your color preferences.</div>";
1862
  $html .= "<script type=\"text/javascript\">
1863
var skin = window.location.search.match(/skin=([^&]*)/)[1];
1864
var uicolor = window.location.search.match(/uicolor=([^&]*)/)[1];
1865
var ckeditorUiColorOnChange = function() {
1866
  var color = CKEDITOR.instances['editor'].getUiColor();
1867
  if (typeof(color) != 'undefined') {
1868
    document.getElementsByName('uicolor_user').value = parent.document.getElementsByName('uicolor_user')[0].value = color;
1869
    var edit_uicolor = parent.document.getElementById('edit-uicolor');
1870
    for (i=0; i<edit_uicolor.options.length; i++) {
1871
      if (edit_uicolor[i].value == 'custom') {
1872
        edit_uicolor.selectedIndex = i;
1873
        edit_uicolor[i].selected = 'selected';
1874
        break;
1875
      }
1876
    }
1877
  }
1878
};
1879
CKEDITOR.on('dialogDefinition', function( ev ) {
1880
  var dialogName = ev.data.name;
1881
  var dialogDefinition = ev.data.definition;
1882

    
1883
  if (dialogName == 'uicolor') {
1884
    dialogDefinition.getContents('tab1').get('configBox').style = 'display:none';
1885
  }
1886
});
1887
CKEDITOR.replace('editor', {
1888
  extraPlugins : 'uicolor',
1889
  height: 330,
1890
  uiColor: '#' + uicolor,
1891
  toolbar : [[ 'Bold', 'Italic', '-', 'NumberedList', 'BulletedList'],[ 'UIColor' ]],
1892
  skin: skin,
1893
  on: {
1894
    configLoaded: function(ev) {
1895
      var ckeditor_ver = CKEDITOR.version.split('.')[0];
1896
      if (ckeditor_ver == 3) {
1897
        if (skin != 'kama') {
1898
          ev.editor.config.toolbar = [[ 'Bold', 'Italic', '-', 'NumberedList', 'BulletedList']];
1899
        }
1900
      }
1901
      else {
1902
        CKEDITOR.plugins.addExternal('uicolor', '{$module_drupal_path}/includes/uicolor/', 'plugin.js');
1903
        if (uicolor.length == 0 || uicolor == 'default') {
1904
          delete ev.editor.config.uiColor;
1905
        }
1906
      }
1907
    },
1908
    blur: ckeditorUiColorOnChange,
1909
    focus: ckeditorUiColorOnChange
1910
  }
1911
});
1912
</script>";
1913
  $html .= "</body>";
1914
  $html .= "</html>";
1915
  echo $html;
1916
}