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 85ad3d82 Assos Assos
<?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 6fd71452 Julien Enselme
  if ($editor_path != '<URL>' && !_ckeditor_requirements_isinstalled()) {
48 85ad3d82 Assos Assos
    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 6fd71452 Julien Enselme
  $current_path = ckeditor_path('relative');
257
  if ($current_path == '<URL>') {
258
    $current_path = ckeditor_path('url');
259
  }
260 85ad3d82 Assos Assos
  $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 6fd71452 Julien Enselme
        '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 ed353324 Assos Assos
      '!cdn' => '<strong>//cdn.ckeditor.com/4.4.3/full-all</strong>'
270 85ad3d82 Assos Assos
        )
271
    ) .
272 6fd71452 Julien Enselme
    '<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 85ad3d82 Assos Assos
      '!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 6fd71452 Julien Enselme
      '!path' => '<code>' . $current_path . '</code>'
285 85ad3d82 Assos Assos
        )
286
    ),
287
    '#required' => TRUE
288
  );
289
290 6fd71452 Julien Enselme
  $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 85ad3d82 Assos Assos
  $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 6fd71452 Julien Enselme
      '!path' => '<code>' . $local_path . '</code>'
308 85ad3d82 Assos Assos
        )
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 6fd71452 Julien Enselme
  if ($edit['ckeditor_path'] && 0 !== strpos($edit['ckeditor_path'], "/") && 0 !== strpos($edit['ckeditor_path'], "%") && !preg_match("|^http(s)?://|i", $edit['ckeditor_path'])) {
514 85ad3d82 Assos Assos
    //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 6fd71452 Julien Enselme
function ckeditor_admin_profile_form($form, $form_state, $task, $profile = NULL) {
569 85ad3d82 Assos Assos
  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 6fd71452 Julien Enselme
  // 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 85ad3d82 Assos Assos
  $form['basic'] = array(
601
    '#type' => 'fieldset',
602
    '#title' => t('Basic setup'),
603
    '#collapsible' => TRUE,
604
    '#collapsed' => TRUE
605
  );
606
607 6fd71452 Julien Enselme
  switch ($task) {
608 85ad3d82 Assos Assos
    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 6fd71452 Julien Enselme
  if ($task == 'edit' && !empty($profile->name)) {
653 85ad3d82 Assos Assos
    $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 6fd71452 Julien Enselme
    if (($task == 'edit' && !empty($profile->input_formats) && array_key_exists($format->format, $profile->input_formats)) || !array_key_exists($format->format, $used_formats)) {
664 85ad3d82 Assos Assos
      $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 6fd71452 Julien Enselme
  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 85ad3d82 Assos Assos
  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 6fd71452 Julien Enselme
    drupal_add_library('system', 'ui.widget');
778
    drupal_add_library('system', 'ui.sortable');
779 85ad3d82 Assos Assos
    drupal_add_js($module_drupal_url_path . '/includes/jqueryUI/sort.js', 'file');
780
  }
781
782 6fd71452 Julien Enselme
  $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 85ad3d82 Assos Assos
  $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 6fd71452 Julien Enselme
    '#markup' => '<iframe frameborder="0" id="skinframe" marginheight="0" marginwidth="0" src="' . $skinframe_url . '" style="height:430px;width:700px;"></iframe><br/>',
857 85ad3d82 Assos Assos
    '#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 6fd71452 Julien Enselme
  if ($editor_local_path != '<URL>' && file_exists($editor_local_path . '/plugins/divarea/plugin.js')) {
890 85ad3d82 Assos Assos
    $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 6fd71452 Julien Enselme
  $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 85ad3d82 Assos Assos
  $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 6fd71452 Julien Enselme
  $current_theme = variable_get('theme_default', $theme);
1082
  $theme_path = drupal_get_path('theme', $current_theme);
1083
1084 85ad3d82 Assos Assos
  $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 6fd71452 Julien Enselme
      '!theme' => '<code>' . base_path() . $theme_path . '/</code>'
1122 85ad3d82 Assos Assos
        )
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 6fd71452 Julien Enselme
      '!theme' => '<code>' . $theme_path . '/ckeditor.styles.js' . '</code>'
1140 85ad3d82 Assos Assos
        )
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 6fd71452 Julien Enselme
      '!theme' => '<code>' . base_path() . $theme_path . '/</code>',
1164 85ad3d82 Assos Assos
      '!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 6fd71452 Julien Enselme
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 85ad3d82 Assos Assos
  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 6fd71452 Julien Enselme
function ckeditor_admin_profile_clone_form($form, $form_state, $task, $oldprofile) {
1545
  return ckeditor_admin_profile_form($form, $form_state, $task, $oldprofile);
1546 85ad3d82 Assos Assos
}
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 6fd71452 Julien Enselme
  // 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 85ad3d82 Assos Assos
  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 6fd71452 Julien Enselme
  $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 85ad3d82 Assos Assos
    $result['ckeditor_basic.js'] = 'ckeditor_basic.js';
1683
  }
1684 6fd71452 Julien Enselme
  if (file_exists($ckeditor_local_path . '/ckeditor_source.js')) {
1685 85ad3d82 Assos Assos
    $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 6fd71452 Julien Enselme
    'NewPage' => array('name' => 'NewPage', 'icon' => $path . '/images/buttons/newpage.png', 'title' => 'New Page', 'row' => 1),
1716 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    'Print' => array('name' => 'Print', 'icon' => $path . '/images/buttons/print.png', 'title' => 'Print', 'row' => 1),
1724 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    'Textarea' => array('name' => 'Textarea', 'icon' => $path . '/images/buttons/textarea.png', 'title' => 'Textarea', 'row' => 1),
1737 6fd71452 Julien Enselme
    'Select' => array('name' => 'Select', 'icon' => $path . '/images/buttons/select.png', 'title' => 'Selection Field', 'row' => 1),
1738 85ad3d82 Assos Assos
    'Button' => array('name' => 'Button', 'icon' => $path . '/images/buttons/button.png', 'title' => 'Button', 'row' => 1),
1739 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
    'HorizontalRule' => array('name' => 'HorizontalRule', 'icon' => $path . '/images/buttons/horizontalrule.png', 'title' => 'Insert Horizontal Line', 'row' => 2),
1767 85ad3d82 Assos Assos
    'Smiley' => array('name' => 'Smiley', 'icon' => $path . '/images/buttons/smiley.png', 'title' => 'Smiley', 'row' => 2),
1768 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
    '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 85ad3d82 Assos Assos
    'Maximize' => array('name' => 'Maximize', 'icon' => $path . '/images/buttons/maximize.png', 'title' => 'Maximize', 'row' => 3),
1777 6fd71452 Julien Enselme
    'ShowBlocks' => array('name' => 'ShowBlocks', 'icon' => $path . '/images/buttons/showblocks.png', 'title' => 'Show Blocks', 'row' => 3),
1778 85ad3d82 Assos Assos
    '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 6fd71452 Julien Enselme
  if ($editor_path == '<URL>')
1850
    $editor_path = ckeditor_path('url');
1851 85ad3d82 Assos Assos
  $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 6fd71452 Julien Enselme
  height: 330,
1890 85ad3d82 Assos Assos
  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
}