/[drupal]/contributions/modules/fckeditor/fckeditor.module
ViewVC logotype

Contents of /contributions/modules/fckeditor/fckeditor.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.25 - (show annotations) (download) (as text)
Wed Feb 13 15:39:17 2008 UTC (21 months, 2 weeks ago) by wwalc
Branch: MAIN
CVS Tags: HEAD
Changes since 1.24: +2 -2 lines
File MIME type: text/x-php
Removed the fckeditor_global_profile_delete call
1 <?php
2 // $Id: fckeditor.module,v 1.24 2008/02/12 18:58:53 wwalc Exp $
3 /**
4 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
5 * Copyright (C) 2003-2007 Frederico Caldeira Knabben
6 *
7 * == BEGIN LICENSE ==
8 *
9 * Licensed under the terms of any of the following licenses at 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 * FCKeditor Module for Drupal 5.x
25 *
26 * This module allows Drupal to replace textarea fields with FCKeditor.
27 *
28 * This HTML text editor brings to the web many of the powerful functionalities
29 * of known desktop editors like Word. It's really lightweight and doesn't
30 * require any kind of installation on the client computer.
31 */
32
33 /**
34 * The name of simplified toolbar which should be forced
35 * Be sure that this toolbar is defined in fckeditor.config.js or fckconfig.js
36 */
37 define('FCKEDITOR_FORCE_SIMPLE_TOOLBAR_NAME', 'DrupalBasic') ;
38
39 /**
40 * Implementation of hook_help
41 */
42 function fckeditor_help($path, $arg) {
43 if (strpos($path, 'admin/settings/fckeditor/edit/') === 0 || $path == 'admin/settings/fckeditor/add') {
44 $output = t("<p>Note: FCKeditor is highly configurable. The most commonly used features are listed below. If you want to take a look at all available settings, open <code>!fckconfig</code> and then customize <code>!fckeditor_config</code> to your needs. This is also the only way to define new toolbar sets. It is advised to not edit <code>fckconfig.js</code> because you may overwrite it accidentally when you update the editor.</p>", array('!fckconfig' => drupal_get_path('module', 'fckeditor') ."/fckeditor/fckconfig.js", '!fckeditor_config' => drupal_get_path('module', 'fckeditor') ."/fckeditor.config.js"));
45 }
46
47 switch ($path) {
48 case 'admin/settings/help#description':
49 $output = t("Enables the usage of FCKeditor (WYSIWYG editor) instead of plain text fields.");
50 break;
51 case 'admin/settings/fckeditor/addg':
52 case 'admin/settings/fckeditor/editg':
53 $output = t("<p>The Global Profile allows you to define settings that are common for all profiles. Values defined in other profiles will be appended to the global configuration. This way you can avoid repeating some of the settings that are usually the same in each profile.</p>");
54 break;
55 case 'admin/settings/fckeditor':
56 $output = t("<p>The FCKeditor module allows Drupal to replace textarea fields with a rich text or <acronym title=\"What You See Is What You Get\">WYSIWYG</acronym> editor. This editor brings many of the powerful functionalities of known desktop editors like Word to the web. It's relatively lightweight and doesn't require any kind of installation on the client computer.</p><p>More information about the editor is located at the !fckeditorlink. A small user guide is located at !userguidelink.</p>",
57 array(
58 '!fckeditorlink' => l(t('FCKeditor homepage'), 'http://www.fckeditor.net'),
59 '!userguidelink' => l(t('FCKeditor userguide'), 'http://docs.fckeditor.net/FCKeditor/Users_Guide'))
60 );
61 $output .= t('<p>Profiles can be defined based on user roles. A FCKeditor profile can define which pages receive this FCKeditor capability, what buttons or themes are enabled for the editor, how the editor is displayed, and a few other editor functions. It is possible also to define the Global Profile that will hold values that will be appended to all other profiles.</p><p>Lastly, only users with the <code>!access1</code> !permission will be able to use FCKeditor. </p>', array('!permission' => l(t('permission'), 'admin/user/permissions'), '!access1' => t('access fckeditor')));
62 break;
63 case 'admin/help#fckeditor':
64 $output = t("<p>The FCKeditor module allows Drupal to replace textarea fields with a rich text or <acronym title=\"What You See Is What You Get\">WYSIWYG</acronym> editor. This editor brings many of the powerful functionalities of known desktop editors like Word to the web. It's relatively lightweight and doesn't require any kind of installation on the client computer.</p><p>More information is located at the !fckeditorlink. A small user guide is located at !userguidelink.</p>",
65 array(
66 '!fckeditorlink' => l(t('FCKeditor homepage'), 'http://www.fckeditor.net'),
67 '!userguidelink' => l(t('FCKeditor userguide'), 'http://docs.fckeditor.net/FCKeditor/Users_Guide'))
68 );
69 $output .= t('<h3>Installation</h3><p>Go to the !fckeditorlink and download the latest version. Then uncompress the contents of the "fckeditor" directory of the downloaded file to %fckeditordir.</p>',
70 array(
71 '!fckeditorlink' => l(t('FCKeditor homepage'), 'http://www.fckeditor.net/download'),
72 '%fckeditordir' => base_path() . drupal_get_path('module', 'fckeditor') .'/fckeditor/')
73 );
74 $output .= t('<h3>Configuration</h3><ol><li>Enable the module as usual from Drupal\'s admin pages.</li><li>Grant permissions for use of FCKeditor in <code>!path2</code></li><li>Under <code>!path1</code>, create the fckeditor profiles. In each profile you can choose which textareas will be replaced by FCKeditor, select default toolbar and configure some more advanced settings </li><li>For the Rich Text Editing to work you also need to configure your !filterlink for the users that may access Rich Text Editing. Either grant those users Full HTML access or use the following: <br/><code>!filter</code>. </li><li>To have a better control over line breaks, you may disable <code>Line break converter</code> in the chosen filter (recommended).</li><li>Modify the fckeditor.config.js file to custom your needs (optional).<br />You may copy the needed configuration lines from the default FCKeditor configuration settings (modules/fckeditor/fckeditor/fckconfig.js), the lines in fckeditor.config.js will override most settings.</li></ol>',
75 array(
76 '!path1' => l(t('Administer > Settings > FCKeditor'), 'admin/settings/fckeditor'),
77 '!path2' => l(t('Administer > User Management > Access Control'), 'admin/user/permissions'),
78 '!filter' => htmlentities('<a> <p> <span> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area>
79 <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <tr> <td> <em>
80 <b> <u> <i> <strong> <font> <del> <ins> <sub> <sup> <quote> <blockquote>
81 <pre> <address> <code> <cite> <embed> <object> <strike> <caption>'),
82 '!filterlink' => l(t('filters'), 'admin/settings/filters'))
83 );
84 $output .= t('<h3>Installation troubleshooting</h3><p>If your FCKeditor does not show you must check if all files are extracted correctly. The directory %fckeditordir should have the following files <code>fckeditor.js, fckconfig.js, fckstyles.xml, fcktemplates.xml</code> and a directory named <code>editor</code>.</p>',
85 array(
86 '%fckeditordir' => base_path() . drupal_get_path('module', 'fckeditor') .'/fckeditor/')
87 );
88 $output .= t('The correct directory structure is as follows: <blockquote><pre>!structure</pre></blockquote>', array(
89 '!structure' => "modules\n fckeditor\n <em>fckeditor.module</em>\n fckeditor\n _samples\n editor\n <em>COPY_HERE.txt</em>\n <em>fckconfig.js</em>\n ..."
90 ));
91 $output .= t("<h3>Plugins: Teaser break and Pagebreak</h3><p>By default, FCKeditor module comes with two plugins that can handle teaser break (&lt;!--break--&gt;) and pagebreak (&lt;!--pagebreak--&gt;). You can enable any (or even both) of them.<ol><li>Open <code>!fckeditor.config.js</code> and uncomment these three lines: <pre>!code</pre></li><li>The second step is to add buttons to the toolbar (in the same file). The button names are: <code>DrupalBreak, DrupalPageBreak</code>. For example if you have a toolbar with an array of buttons defined as follows: <pre>!buttons1</pre> simply add those two buttons at the end of array: <pre>!buttons2</pre> (remember about single quotes).</li></ol></p>",
92 array(
93 '!fckeditor.config.js' => base_path() . drupal_get_path('module', 'fckeditor') .'/fckeditor.config.js',
94 '!code' => "
95 FCKConfig.PluginsPath = '../../plugins/' ;
96 FCKConfig.Plugins.Add( 'drupalbreak' ) ;
97 FCKConfig.Plugins.Add( 'drupalpagebreak' ) ;
98 ",
99 '!buttons1' => "['Image','Flash','Table','Rule','SpecialChar']",
100 '!buttons2' => "['Image','Flash','Table','Rule','SpecialChar', 'DrupalBreak', 'DrupalPageBreak']",
101 ));
102 $output .= t('<h3>Uploading images and files</h3><p>There are three ways of uploading files: By using the built-in file browser, by using a module like !imce or using the core upload module.</p>',
103 array(
104 '!imce' => l(t('IMCE'), 'http://drupal.org/project/imce')
105 )
106 );
107 // the rest is untranslated for the moment
108 $output .= t("<h3>How to enable the file browser</h3><p>The editor gives the end user the flexibility to create a custom file browser that can be integrated on it. The included file browser allows users to view the content of a specific directory on the server and add new content to that directory (create folders and upload files).</p><p><ol><li>To enable file browsing you need to edit the connector configuration file in your fckeditor module directory, the file should be in:<blockquote><code>!config3</code> <br/> (FCKeditor 2.5+)<br/><br/> or <br/><br/><code>!config1</code><br/> and <br/><code>!config2</code> <br/> (FCKeditor 2.3.x - 2.4.x)</blockquote></p><p>In this file(s) you will need to enable the file browser by adding one line that includes file with the special authentication function for Drupal (<code>filemanager.config.php</code>). Add this code: <blockquote><code>!code1</code><br/> (FCKeditor 2.5+)</blockquote> or <blockquote><code>!code2</code> <br/> (FCKeditor 2.3.x - 2.4.x)</blockquote> straight below this line: <blockquote><code>!code3</code></blockquote> The config.php file also holds some other important settings, please take a look at it and adjust it to your needs (optional).</p></li>",
109 array('!config1' => base_path() . drupal_get_path('module', 'fckeditor') ."/fckeditor/editor/filemanager/browser/default/connectors/php/config.php",
110 '!config2' => base_path() . drupal_get_path('module', 'fckeditor') ."/fckeditor/editor/filemanager/upload/php/config.php",
111 '!config3' => base_path() . drupal_get_path('module', 'fckeditor') ."/fckeditor/editor/filemanager/connectors/php/config.php",
112 '!filesdir' => file_directory_path(),
113 '!code1' => 'require_once "../../../../../filemanager.config.php";', //2.5
114 '!code2' => 'require_once "'. str_replace("\\", "\\\\", dirname(__FILE__) . DIRECTORY_SEPARATOR .'filemanager.config.php"'), //2.4
115 '!code3' => "\$Config['UserFilesAbsolutePath'] = '' ;",
116 )
117 );
118 $output .= t("<li>As of Drupal 5.2, additional step is required: locate file named <code>settings.php</code> inside your drupal directory (usually <code>sites/default/settings.php</code>) and set <strong><code>&#36;cookie_domain</code></strong> variable to the appropiate domain (remember to uncomment that line). If you not do this, FCKeditor will claim that file browser is disabled</li>");
119 $output .= t('<li>Enabling file uploads is <strong>a security risk</strong>. That\'s why you have to grant a !link to enable the file browser to certain groups.</li>', array('!link' => l(t('separate permission'), 'admin/user/permissions')));
120 $output .= t('<li>Lastly, adjust the !fb for each !profile.</li></ol>', array('!fb' => t('File browser settings'), '!profile' => l(t('profile'), 'admin/settings/fckeditor')));
121 //$output .= t("<h3>Modules: Image Assist</h3><p>Image Assist can be integrated with FCKeditor. To do this, simply copy the <code>!iaf1</code> file to <code>!iaf2</code>.</p>", array("!iaf1" => drupal_get_path('module', 'fckeditor') ."/img_assist_fckeditor.js", "!iaf2" => drupal_get_path('module', 'img_assist') ."/img_assist_fckeditor.js"));
122
123 break;
124 }
125 return $output;
126 }
127
128 /**
129 * Implementation of hook_perm
130 * Administer -> User management -> Access Control
131 */
132 function fckeditor_perm() {
133 return array('administer fckeditor', 'access fckeditor', 'allow fckeditor file uploads');
134 }
135
136
137 /**
138 * Implementation of textarea
139 * Replace textarea with FCKeditor using callback function (fckeditor_process_textarea)
140 */
141 function fckeditor_elements() {
142 $type = array();
143 if (user_access('administer fckeditor')) {
144 $type['textfield'] = array(
145 '#process' => array(
146 'fckeditor_process_input'
147 ),
148 );
149 }
150 if (user_access('access fckeditor')) {
151 // only roles with permission get the fckeditor
152 if (fckeditor_is_compatible_client()) {
153 // it would be useless to dig deeper if we're not able or allowed to
154 $type['textarea'] = array(
155 '#process' => array(
156 'fckeditor_process_textarea'
157 ),
158 );
159 }
160 }
161 return $type;
162 }
163
164 /**
165 * Allow more than 255 chars in Allowed HTML tags textfield
166 *
167 */
168 function fckeditor_process_input($element) {
169 if ($element['#id']=='edit-allowed-html-1') {
170 $element['#maxlength'] = max($element['#maxlength'], 1024);
171 }
172 return $element;
173 }
174
175 /**
176 * Add link to FCKeditor configuration in "Administer -> Site configuration" section
177 *
178 */
179 function fckeditor_menu() {
180
181 $items = array();
182
183 $items['admin/settings/fckeditor'] = array(
184
185 'title' => t('FCKeditor'),
186 'description' => t('Configure the rich editor.'),
187 'page callback' => 'fckeditor_admin',
188 'access arguments' => array('administer fckeditor'),
189 'type' => MENU_NORMAL_ITEM,
190 );
191
192 return $items;
193 }
194
195 //Remove a profile from the database.
196 function fckeditor_profile_delete($name) {
197 db_query("DELETE FROM {fckeditor_settings} WHERE name = '%s'", $name);
198 db_query("DELETE FROM {fckeditor_role} WHERE name = '%s'", $name);
199 }
200
201 /**
202 * Profile validation.
203 */
204 function fckeditor_profile_validate($edit) {
205 $errors = array();
206
207 if (!preg_match("/^\d+$/", trim($edit['min_rows']))) {
208 $errors['min_rows'] = t('Minimum rows must be a valid number');
209 }
210
211 if ($edit['default'] == 't' && $edit['popup'] == 't') {
212 $errors['popup'] = t('If FCKeditor is enabled by default, popup window must be disabled.');
213 }
214
215 if ($edit['show_toggle'] == 't' && $edit['popup'] == 't') {
216 $errors['popup'] = t('If toggle is enabled, popup window must be disabled.');
217 }
218
219 if (!$edit['name']) {
220 $errors['name'] = t('You must give a profile name.');
221 }
222
223 if (!preg_match("/^\d+%?$/", $edit['width'])) {
224 $errors['width'] = t('Enter valid width. Ex: 400 or 100%');
225 }
226
227 if (!empty($edit['css_path'])) {
228 if ($edit['css_mode'] != 'self') {
229 $errors['css_path'] = t('CSS path is not empty. Please set the "Editor CSS" option to "define css" mode.');
230 }
231 else if (false !== strpos($edit['css_path'], '"')) {
232 $errors['css_path'] = t('Double quotes are not allowed in CSS path.');
233 }
234 else if (substr($edit['css_path'], 0, 1) == "'" && substr($edit['css_path'], -1) == "'") {
235 $errors['css_path'] = t('Enter valid path, do not surround it with quotes.');
236 }
237 }
238
239 if (!empty($edit['styles_path'])) {
240 if ($edit['css_style'] != 'self') {
241 $errors['styles_path'] = t('Path to predefined styles is not empty. Please set the "Predefined styles" option to "define path to fckstyles.xml" mode.');
242 }
243 else if (false !== strpos($edit['styles_path'], '"')) {
244 $errors['styles_path'] = t('Double quotes are not allowed in path.');
245 }
246 else if (substr($edit['styles_path'], 0, 1) == "'" && substr($edit['styles_path'], -1) == "'") {
247 $errors['styles_path'] = t('Enter valid path, do not surround it with quotes.');
248 }
249 }
250
251 if (!empty($edit['font_format'])) {
252 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'])) {
253 $errors['font_format'] = t('Enter valid, semicolon separated, list of HTML font formats (no semicolon at the end of list expected).');
254 }
255 }
256
257 //validate fields
258 $fields = preg_split("/[\s,]+/", strip_tags($edit['excl_fields']));
259 foreach ($fields as $field) {
260 if ($field && !preg_match("/^[a-z]+(\-[a-z]+)+$/i", $field)) {
261 $errors['excl_fields'] = t("Invalid field specified: %1", array("%1" => $field));
262 break;
263 }
264 }
265
266 $fields = preg_split("/[\s,]+/", strip_tags($edit['simple_incl_fields']));
267 foreach ($fields as $field) {
268 if ($field && !preg_match("/^[a-z]+(\-[a-z]+)+$/i", $field)) {
269 $errors['excl_fields'] = t("Invalid field specified: %1", array("%1" => $field));
270 break;
271 }
272 }
273
274 //validate paths
275 $paths = preg_split("/[\s,]+/", strip_tags($edit['excl_paths']));
276 foreach ($paths as $path) {
277 if ($path && !preg_match("|^[a-z0-9-\*/]*$|i", $path)) {
278 $errors['excl_paths'] = t("Invalid path specified: %1", array("%1" => $path));
279 break;
280 }
281 }
282
283 $paths = preg_split("/[\s,]+/", strip_tags($edit['simple_incl_paths']));
284 foreach ($paths as $path) {
285 if ($path && !preg_match("|^[a-z0-9-\*/]*$|i", $path)) {
286 $errors['excl_paths'] = t("Invalid path specified: %1", array("%1" => $path));
287 break;
288 }
289 }
290
291 if ($edit['UserFilesAbsolutePath'] && !$edit['UserFilesPath']) {
292 $errors['UserFilesPath'] = t("Path to uploaded files is required.");
293 }
294 if ($edit['UserFilesPath'] && !$edit['UserFilesAbsolutePath']) {
295 $errors['UserFilesPath'] = t("Absolute path to uploaded files is required.");
296 }
297
298 foreach ($errors as $name => $message) {
299 form_set_error($name, $message);
300 }
301
302 return count($errors) == 0;
303 }
304
305 /**
306 * Global profile validation.
307 */
308 function fckeditor_global_profile_validate($edit) {
309 $errors = array();
310
311 //validate fields
312 $fields = preg_split("/[\s,]+/", strip_tags($edit['excl_fields']));
313 foreach ($fields as $field) {
314 if ($field && !preg_match("/^[a-z]+(\-[a-z]+)+$/i", $field)) {
315 $errors['excl_fields'] = t("Invalid field specified: %1", array("%1" => $field));
316 break;
317 }
318 }
319
320 $fields = preg_split("/[\s,]+/", strip_tags($edit['simple_incl_fields']));
321 foreach ($fields as $field) {
322 if ($field && !preg_match("/^[a-z]+(\-[a-z]+)+$/i", $field)) {
323 $errors['excl_fields'] = t("Invalid field specified: %1", array("%1" => $field));
324 break;
325 }
326 }
327
328 //validate paths
329 $paths = preg_split("/[\s,]+/", strip_tags($edit['excl_paths']));
330 foreach ($paths as $path) {
331 if ($path && !preg_match("|^[a-z0-9-\*/]*$|i", $path)) {
332 $errors['excl_paths'] = t("Invalid path specified: %1", array("%1" => $path));
333 break;
334 }
335 }
336
337 $paths = preg_split("/[\s,]+/", strip_tags($edit['simple_incl_paths']));
338 foreach ($paths as $path) {
339 if ($path && !preg_match("|^[a-z0-9-\*/]*$|i", $path)) {
340 $errors['excl_paths'] = t("Invalid path specified: %1", array("%1" => $path));
341 break;
342 }
343 }
344
345 foreach ($errors as $name => $message) {
346 form_set_error($name, $message);
347 }
348
349 return count($errors) == 0;
350 }
351
352 /**
353 * Controller for FCKeditor administrative settings.
354 */
355 function fckeditor_admin($arg = NULL) {
356
357 $module_drupal_path = drupal_get_path('module', 'fckeditor');
358 $fckconfig_file = $module_drupal_path .'/fckeditor/fckconfig.js';
359 if (!file_exists($fckconfig_file)) {
360 drupal_set_message(t('checking for %filename', array('%filename' => $fckconfig_file)));
361 drupal_set_message(
362 t('The FCKeditor component is not installed correctly. Please go to the !fckeditorlink to download the latest version. After that you must extract the files to %modulepath and make sure that the directory %modulesubdir and the file %modulefile exist. Refer to the !readme for more information.',
363 array(
364 '!fckeditorlink' => l(t('FCKeditor homepage'), 'http://www.fckeditor.net/download'),
365 '!readme' => l('readme.txt', 'admin/help/fckeditor'),
366 '%modulepath' => base_path() . $module_drupal_path .'/fckeditor/',
367 '%modulesubdir' => base_path() . $module_drupal_path .'/fckeditor/editor',
368 '%modulefile' => base_path() . $module_drupal_path .'/fckeditor/fckeditor.js')),
369 'error');
370 return false;
371 }
372
373 $edit = $_POST;
374 $op = isset($_POST['op']) ? $_POST['op'] : "";
375
376 $op = $arg && !$op ? $arg : $op;
377
378 switch ($op) {
379 case 'add':
380 $output = fckeditor_profile_form($edit);
381 break;
382
383 case 'addg':
384 $output = fckeditor_global_profile_form($edit);
385 break;
386
387 case 'edit':
388 drupal_set_title(t('Edit FCKeditor profile'));
389 $output = fckeditor_profile_form(fckeditor_profile_load(urldecode(arg(4))));
390 break;
391
392 case 'editg':
393 drupal_set_title(t('Edit FCKeditor profile'));
394 $output = fckeditor_global_profile_form(fckeditor_profile_load("FCKeditor Global Profile"));
395 break;
396
397 case 'delete':
398 fckeditor_profile_delete(urldecode(arg(4)));
399 drupal_set_message(t('Deleted profile'));
400 drupal_goto('admin/settings/fckeditor');
401 break;
402
403 case 'deleteg':
404 fckeditor_profile_delete("FCKeditor Global Profile");
405 drupal_set_message(t('Deleted Global profile'));
406 drupal_goto('admin/settings/fckeditor');
407 break;
408
409 case t('Create profile');
410 case t('Update profile');
411 if (fckeditor_profile_validate($edit)) {
412 fckeditor_profile_save($edit);
413 $edit['old_name'] ? drupal_set_message(t('Your FCKeditor profile has been updated.')) : drupal_set_message(t('Your FCKeditor profile has been created.'));
414 drupal_goto('admin/settings/fckeditor');
415 }
416 else {
417 $output = fckeditor_profile_form($edit);
418 }
419 break;
420
421 case t('Create global profile');
422 case t('Update global profile');
423 if (fckeditor_global_profile_validate($edit)) {
424 $edit['name'] = 'FCKeditor Global Profile';
425 fckeditor_global_profile_save($edit);
426 drupal_set_message(t('FCKeditor global profile has been saved.'));
427 drupal_goto('admin/settings/fckeditor');
428 }
429 else {
430 $output = fckeditor_global_profile_form($edit);
431 }
432 break;
433
434 default:
435 drupal_set_title(t('FCKeditor settings'));
436 //Check if FCKeditor is installed.
437 $fckeditor_loc = drupal_get_path('module', 'fckeditor') .'/fckeditor/';
438 if (!is_dir($fckeditor_loc)) {
439 drupal_set_message(t('Could not find the FCKeditor engine installed at <strong>!fckeditor-directory</strong>. Please !download, uncompress it and copy the folder into !fckeditor-path.', array('!fckeditor-path' => drupal_get_path('module', 'fckeditor'), '!fckeditor-directory' => $fckeditor_loc, '!download' => l(t("download FCKeditor"), "http://www.fckeditor.net/download"))), 'error');
440 }
441 $output = fckeditor_profile_overview();
442 }
443
444 return $output;
445 }
446
447 /**
448 * Save a profile to the database.
449 * @todo add more entries to array in the user_save line
450 */
451 function fckeditor_profile_save($edit) {
452 db_query("DELETE FROM {fckeditor_settings} WHERE name = '%s' or name = '%s'", $edit['name'], $edit['old_name']);
453 db_query("DELETE FROM {fckeditor_role} WHERE name = '%s' or name = '%s'", $edit['name'], $edit['old_name']);
454 db_query("INSERT INTO {fckeditor_settings} (name, settings) VALUES ('%s', '%s')", $edit['name'], serialize($edit));
455 if ($edit['rids'])
456 foreach ($edit['rids'] as $rid => $value) {
457 db_query("INSERT INTO {fckeditor_role} (name, rid) VALUES ('%s', %d)", $edit['name'], $rid);
458 }
459
460 // if users can't set their own defaults, make sure to remove $user->fckeditor_status so their default doesn't override the main default
461 if ($edit['user_choose'] == 'false') {
462 global $user;
463 user_save($user, array('fckeditor_status' => NULL));
464 }
465 }
466
467 function fckeditor_global_profile_save($edit) {
468 if (isset($edit['rank'])) {
469 $edit['rank'] = explode('>', str_replace(' ', '', $edit['rank']));
470 }
471
472 db_query("DELETE FROM {fckeditor_settings} WHERE name = '%s' or name = '%s'", $edit['name'], $edit['old_name']);
473 db_query("DELETE FROM {fckeditor_role} WHERE name = '%s' or name = '%s'", $edit['name'], $edit['old_name']);
474 db_query("INSERT INTO {fckeditor_settings} (name, settings) VALUES ('%s', '%s')", $edit['name'], serialize($edit));
475 }
476
477 /**
478 * Controller for fckeditor profiles.
479 */
480 function fckeditor_profile_overview() {
481 $output = '';
482
483 $profiles = fckeditor_profile_load();
484 if ($profiles) {
485 $roles = user_roles();
486 $header = array(t('Profile'), t('Roles'), t('Operations'));
487 foreach ($profiles as $p) {
488 if ($p->name !== "FCKeditor Global Profile") {
489 $rows[] = array(array('data' => $p->name, 'valign' => 'top'), array('data' => implode("<br />\n", $p->rids)), array('data' => l(t('edit'), 'admin/settings/fckeditor/edit/'. urlencode($p->name)) .' '. l(t('delete'), 'admin/settings/fckeditor/delete/'. urlencode($p->name)), 'valign' => 'top'));
490 }
491 }
492 $output .= "<h3>". t("Profiles") ."</h3>";
493 $output .= theme('table', $header, $rows);
494 $output .= '<p>'. l(t('Create new profile'), 'admin/settings/fckeditor/add') .'</p>';
495 }
496 else {
497 drupal_set_message(t('No profiles found. Click here to !create.', array('!create' => l(t("create a new profile"), 'admin/settings/fckeditor/add'))));
498 }
499
500 $rows = array();
501 if (!isset($profiles['FCKeditor Global Profile'])) {
502 drupal_set_message(t('Global Profile not found. Click here to !create.', array('!create' => l(t("create the global profile"), 'admin/settings/fckeditor/addg'))));
503 }
504 else {
505 $output .= "<h3>". t("Global Settings") ."</h3>";
506 $rows[] = array(array('data' => t('FCKeditor Global Profile'), 'valign' => 'top'), array('data' => l(t('edit'), 'admin/settings/fckeditor/editg') ." ". l(t('delete'), 'admin/settings/fckeditor/deleteg'), 'valign' => 'top'));
507 $output .= theme('table', array(t('Profile'), t('Operations')), $rows);
508 }
509
510 return $output;
511 }
512
513 /**
514 * Load all profiles. Just load one profile if $name is passed in.
515 */
516 function fckeditor_profile_load($name = '') {
517 static $profiles = array();
518
519 if (!$profiles) {
520 $roles = user_roles();
521 $result = db_query('SELECT * FROM {fckeditor_settings}');
522 while ($data = db_fetch_object($result)) {
523 $data->settings = unserialize($data->settings);
524 $result2 = db_query("SELECT rid FROM {fckeditor_role} WHERE name = '%s'", $data->name);
525 $role = array();
526 while ($r = db_fetch_object($result2)) {
527 $role[$r->rid] = $roles[$r->rid];
528 }
529 $data->rids = $role;
530
531 $profiles[$data->name] = $data;
532 }
533 }
534
535 return ($name ? $profiles[$name] : $profiles);
536 }
537
538 /**
539 * @param int $excl_mode 1/include, exclude otherwise
540 * @param string $excl_fields fields (HTML IDs)
541 * @param string $excl_paths paths (drupal paths)
542 * @param string $element_id current ID
543 * @param string $get_q current path
544 *
545 * @return boolean
546 * returns true if FCKeditor is enabled
547 */
548 function fckeditor_is_enabled($excl_mode, $excl_fields, $excl_paths, $element_id, $get_q) {
549 $arr_excl_fields = preg_split("/[\s,]+/", strip_tags($excl_fields));
550 $field_found = fckeditor_idsearch($element_id, $arr_excl_fields);
551
552 $path = drupal_get_path_alias($get_q);
553 $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($excl_paths, '/')) .')$/';
554 $path_found = preg_match($regexp, $path);
555
556 $found = $field_found || $path_found;
557
558 $result = ($excl_mode == 1) ? $found : !$found;
559 return $result;
560 }
561
562 /**
563 * This function create the HTML objects required for the FCKeditor
564 *
565 * @param $element
566 * A fully populated form elment to add the editor to
567 * @return
568 * The same $element with extra FCKeditor markup and initialization
569 */
570 function fckeditor_process_textarea($element) {
571 static $is_running = FALSE;
572 static $num = 1;
573 global $user, $fckeditor_simple_toolbar_ids;
574 static $profile_name;
575
576 //skip this one, surely nobody wants WYSIWYG here
577
578 switch ($element['#id']) {
579 case 'edit-excl-list':
580 case 'edit-simple-incl-list':
581 case 'edit-simple-incl-paths':
582 case 'edit-simple-incl-fields':
583 case 'edit-log':
584 case 'edit-excl-fields':
585 case 'edit-excl-paths':
586 case 'edit-js-conf':
587 return $element;
588 break;
589 }
590
591 if (isset($element['#attributes']['disabled']) && $element['#attributes']['disabled'] == 'disabled') {
592 return $element;
593 }
594
595 // Since fckeditor_profile_load() makes a db hit, only call it when we're pretty sure
596 // we're gonna render fckeditor.
597 if (!$profile_name) {
598 $sorted_roles = fckeditor_sorted_roles();
599 foreach ($sorted_roles as $rid => $name) {
600 if (isset($user->roles[$rid])) {
601 break;
602 }
603 }
604
605 $profile_name = db_result(db_query("SELECT s.name FROM {fckeditor_settings} s INNER JOIN {fckeditor_role} r ON r.name = s.name WHERE r.rid='%s'", $rid));
606 if (!$profile_name) {
607 return $element;
608 }
609 }
610
611 $profile = fckeditor_profile_load($profile_name);
612
613 $conf = array();
614 $conf = $profile->settings;
615
616 if ($conf['allow_user_conf']=='t') {
617 foreach (array('default', 'show_toggle', 'popup', 'skin', 'toolbar', 'expand', 'width', 'lang', 'auto_lang') as $setting) {
618 $conf[$setting] = fckeditor_user_get_setting($user, $profile, $setting);
619 }
620 }
621 if ($conf["popup"]=="t" && $conf["show_toggle"]=="t") {
622 $conf["show_toggle"]="f";
623 }
624
625 $themepath = path_to_theme() .'/';
626 $host = base_path();
627
628 // Set resizable to false to avoid drupal.js resizable function from taking control of the textarea
629 if ($conf["popup"]=="f") {
630 $element['#resizable'] = FALSE;
631 }
632
633 $enabled = fckeditor_is_enabled($conf['excl_mode'], $conf['excl_fields'], $conf['excl_paths'], $element['#id'], $_GET['q']);
634 if ($enabled) {
635 $global_profile = fckeditor_profile_load("FCKeditor Global Profile");
636 $global_conf = $global_profile->settings;
637 if ($global_conf) {
638 $enabled = fckeditor_is_enabled($global_conf['excl_mode'], $global_conf['excl_fields'], $global_conf['excl_paths'], $element['#id'], $_GET['q']);
639 }
640 }
641
642 if (($element['#rows'] > $conf['min_rows']) && $enabled) {
643 // only replace textarea when it has enough rows and it is enabled
644
645 $js_id = 'oFCK_'. $num++;
646 $fckeditor_on = ($conf['default']=='t') ? 1 : 0 ;
647
648 $wysiwyg_link = "<div id=\"fck_{$js_id}\"><textarea id=\"{$js_id}\">". htmlspecialchars($element['#value']) ."</textarea></div>\n";
649 $wysiwyg_link .= "<a href=\"javascript:Toggle('{$js_id}','{$element['#id']}','". str_replace("'", "\\'", t("Switch to plain text editor")) ."','". str_replace("'", "\\'", t("Switch to rich text editor")) ."');\" id=\"switch_{$js_id}\" ". ($fckeditor_on?"style=\"display:none\"":"") .">";
650 $wysiwyg_link .= $fckeditor_on ? t("Switch to plain text editor") : t("Switch to rich text editor");
651 $wysiwyg_link .= "</a>";
652 $wysiwyg_link .= "\n<script type=\"text/javascript\">";
653 $wysiwyg_link .= "window.setTimeout(\"CreateToggle('{$element['#id']}','{$js_id}', $fckeditor_on);\",100);\n</script>";
654 if (!isset($element['#suffix'])) {
655 $element['#suffix'] = "";
656 }
657 //settings are saved as strings, not booleans
658 if ($profile->settings['show_toggle'] == 't') {
659 // Make sure to append to #suffix so it isn't completely overwritten
660 $element['#suffix'] .= $wysiwyg_link;
661 }
662 // setting some variables
663 $module_drupal_path = drupal_get_path('module', 'fckeditor');
664 $module_full_path = base_path() . $module_drupal_path;
665 // get the default drupal files path
666 $files_path = base_path() . file_directory_path();
667 // module_drupal_path:
668 // 'modules/fckeditor' (length=17)
669 // module_full_path:
670 // '/drupal5/modules/fckeditor' (length=26)
671 // files_path:
672 // '/drupal5/files' (length=14)
673 // configured in settings
674 $width = $conf['width'];
675
676 // sensible default for small toolbars
677 $height = $element['#rows'] * 14 + 140;
678
679 if (!$is_running) {
680 drupal_add_js($module_drupal_path .'/fckeditor/fckeditor.js');
681 drupal_add_js($module_drupal_path .'/fckeditor.utils.js');
682 $is_running = true;
683 }
684
685 $toolbar = $conf['toolbar'];
686 //$height += 100; // for larger toolbars
687
688 $force_simple_toolbar = fckeditor_is_enabled(1, $conf['simple_incl_fields'], $conf['simple_incl_paths'], $element['#id'], $_GET['q']);
689 if (!$force_simple_toolbar) {
690 $force_simple_toolbar = fckeditor_is_enabled(1, $global_conf['simple_incl_fields'], $global_conf['simple_incl_paths'], $element['#id'], $_GET['q']);
691 }
692 if ($force_simple_toolbar) {
693 $toolbar = FCKEDITOR_FORCE_SIMPLE_TOOLBAR_NAME;
694 }
695
696 $textarea_id = $profile->settings['show_toggle'] == 't' ? $js_id : $element['#id'];
697
698 $element['#suffix'] .= "\n<script type=\"text/javascript\">
699 var ". $js_id ." = new FCKeditor( '". $textarea_id ."' );
700 ". $js_id .".BasePath = '". $module_full_path ."/fckeditor/';
701 ". $js_id .".Config['CustomConfigurationsPath'] = \"". $module_full_path ."/fckeditor.config.js\";
702 ". $js_id .".Config['TextareaID'] = \"". $element['#id'] ."\";";
703
704 //if ($conf['appearance_conf'] == 'f') {
705 $element['#suffix'] .= "\n". $js_id .".ToolbarSet = \"". $toolbar ."\";
706 ". $js_id .".Config['SkinPath'] = ". $js_id .".BasePath + \"editor/skins/". $conf['skin'] ."/\";
707 ". $js_id .".Config['DefaultLanguage'] = \"". $conf['lang'] ."\";
708 ". $js_id .".Config['AutoDetectLanguage'] = ". ($conf['auto_lang']=="t"?"true":"false") .";
709 ". $js_id .".Height = \"". $height ."\";
710 ". $js_id .".Config['ToolbarStartExpanded'] = ". ($conf['expand']=="t"?"true":"false") .";
711 ". $js_id .".Width = \"". $width ."\";\n";
712 //}
713 //if ($conf['output_conf'] == 'f') {
714 $element['#suffix'] .= "\n". $js_id .".Config['EnterMode'] = '". $conf['enter_mode'] ."';
715 ". $js_id .".Config['ShiftEnterMode'] = \"". $conf['shift_enter_mode'] ."\";
716 ". $js_id .".Config['FontFormats'] = \"". str_replace(",", ";", $conf['font_format']) ."\";
717 ". $js_id .".Config['FormatSource'] = ". ($conf['format_source']=="t"?"true":"false") .";
718 ". $js_id .".Config['FormatOutput'] = ". ($conf['format_output']=="t"?"true":"false") .";\n";
719 //}
720
721 // integrate IMCE if it exists and is prefered
722 if (function_exists('imce_integrate') && variable_get('imce_settings_fck', 0)) {
723 imce_integrate('fck');
724 $advanced_uploads = 0;
725 $basic_uploads = 0;
726 }
727 else {
728 $advanced_uploads = ($conf['upload_advanced']=="t");
729 $basic_uploads = ($conf['upload_basic']=="t");
730 }
731 // add code for filebrowser for users that have access
732 if (user_access('allow fckeditor file uploads')==1) {
733 $connector_path = $module_drupal_path ."/fckeditor/editor/filemanager/connectors/php/connector.php" ;
734 $connector_path = file_exists($connector_path) ? "../../connectors/php/connector.php" : "connectors/php/connector.php" ;
735 $upload_path = $module_drupal_path ."/fckeditor/editor/filemanager/connectors/php/upload.php" ;
736 $upload_path = file_exists($upload_path) ? "/fckeditor/editor/filemanager/connectors/php/upload.php" : "/fckeditor/editor/filemanager/upload/php/upload.php" ;
737 if ($advanced_uploads) {
738 $element['#suffix'] .= $js_id .".Config['LinkBrowserURL'] = \"". $module_full_path ."/fckeditor/editor/filemanager/browser/default/browser.html?Connector=". $connector_path ."&ServerPath=". $files_path ."\";
739 ". $js_id .".Config['ImageBrowserURL'] = \"". $module_full_path ."/fckeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=". $connector_path ."&ServerPath=". $files_path ."\";
740 ". $js_id .".Config['FlashBrowserURL'] = \"". $module_full_path ."/fckeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=". $connector_path ."&ServerPath=". $files_path ."\";\n";
741 }
742 else {
743 $element['#suffix'] .= $js_id .".Config['LinkBrowser'] = false;
744 ". $js_id .".Config['ImageBrowser'] = false;
745 ". $js_id .".Config['FlashBrowser'] = false;\n";
746 }
747 if ($basic_uploads) {
748 $element['#suffix'] .= $js_id .".Config['LinkUploadURL'] = \"". $module_full_path . $upload_path ."\";
749 ". $js_id .".Config['ImageUploadURL'] = \"". $module_full_path . $upload_path ."?Type=Image\";
750 ". $js_id .".Config['FlashUploadURL'] = \"". $module_full_path . $upload_path ."?Type=Flash\";\n";
751 }
752 else {
753 $element['#suffix'] .= $js_id .".Config['LinkUpload'] = false;
754 ". $js_id .".Config['ImageUpload'] = false;
755 ". $js_id .".Config['FlashUpload'] = false;\n";
756 }
757 $_SESSION['FCKeditor']['UserFilesPath'] = strtr($profile->settings['UserFilesPath'], array("%f" => file_directory_path(), "%u" => $user->uid, "%b" => base_path()));
758 $_SESSION['FCKeditor']['UserFilesAbsolutePath'] = strtr($profile->settings['UserFilesAbsolutePath'], array("%f" => file_directory_path(), "%u" => $user->uid, "%b" => base_path(), "%d" => $_SERVER['DOCUMENT_ROOT']));
759 }
760 else {
761 $element['#suffix'] .= $js_id .".Config['LinkBrowser'] = false;
762 ". $js_id .".Config['ImageBrowser'] = false;
763 ". $js_id .".Config['FlashBrowser'] = false;
764 ". $js_id .".Config['LinkUpload'] = false;
765 ". $js_id .".Config['ImageUpload'] = false;
766 ". $js_id .".Config['FlashUpload'] = false;\n";
767 }
768
769 if ($conf['js_conf']) {
770 $lines = preg_split("/[\n\r]+/", $conf['js_conf']);
771 foreach ($lines as $l)
772 if ($l && strlen($l) > 5) {
773 $eqpos = strpos($l, "=");
774 if (false !== $eqpos) {
775 $option = str_replace("FCKConfig.", "", substr($l, 0, $eqpos));
776 $element['#suffix'] .= "\n". $js_id .".Config['". $option ."'] =". substr($l, $eqpos + 1);
777 }
778 }
779 }
780
781 // add custom xml stylesheet if it exists
782 if ($conf['css_style'] == 'theme') {
783 if (file_exists($themepath .'/fckstyles.xml')) {
784 $styles_xml_path = $host . $themepath .'/fckstyles.xml';
785 $element['#suffix'] .= $js_id .".Config['StylesXmlPath'] = \"". $styles_xml_path ."\";\n";
786 }
787 }
788 else if ($conf['css_style'] == 'self') {
789 $element['#suffix'] .= $js_id .".Config['StylesXmlPath'] = \"". str_replace(array('%h', '%t', '%m'), array($host, $themepath, $module_drupal_path), $conf['styles_path']) ."\";\n";
790 }
791
792 // add custom stylesheet if configured
793 // lets hope it exists but we'll leave that to the site admin
794 if ($conf['css_mode'] == 'theme') {
795 $css = $themepath .'style.css';
796 if (file_exists($css)) {
797 $element['#suffix'] .= $js_id .".Config['EditorAreaCSS'] = \"". $host . $css .",". $module_full_path ."/fckeditor.css\";";
798 }
799 }
800 else if ($conf['css_mode'] == 'self') {
801 $element['#suffix'] .= $js_id .".Config['EditorAreaCSS'] = \"". str_replace(array('%h', '%t'), array($host, $themepath), $conf['css_path']) .",". $module_full_path ."/fckeditor.css\";";
802 }
803
804 $element['#suffix'] .= "</script>\n";
805
806 if ($conf['popup']=="t") {
807 // Add the script file with the popup open function.
808 drupal_add_js($module_drupal_path .'/fckeditor.popup.js');
809 $element['#suffix'] .= " <span class=\"fckeditor_popuplink\">(<a href=\"#\" onclick=\"FCKeditor_OpenPopup('". $module_full_path ."/fckeditor.popup.html?var=". $js_id ."&el=". $element['#id'] ."');return false;\">". t('Open rich editor') ."</a>)</span>";
810 }
811 else {
812 // if no popup mode, add the editor initialization to the footer
813 // this obviously needs print($closure) in page.tpl.php
814 if ($fckeditor_on) {
815 drupal_add_js('if (Drupal.jsEnabled) {$(document).ready(function() {if (typeof ('. $js_id .') != "undefined") '. $js_id .'.ReplaceTextarea();});}', 'inline', 'footer');
816 }
817 }
818 }
819
820 // display the field id for administrators
821 if (user_access('administer fckeditor')) {
822 $element['#suffix'] .= t('<div class="textarea-identifier description">The ID for !excluding this element is: !id - the path is: !path</div>', array(
823 '!excluding' => l(t("excluding or including"), 'admin/settings/fckeditor'),
824 '!id' => $element['#id'],
825 '!path' => $_GET['q'],
826 ));
827 }
828
829 return $element;
830 }
831
832 /**
833 * Implementation of hook_user().
834 */
835 function fckeditor_user($type, &$edit, &$user, $category = NULL) {
836 if ($type == 'form' && $category == 'account' && user_access('access fckeditor')) {
837 $profile = fckeditor_user_get_profile($user);
838 $toolbar_options = fckeditor_load_toolbar_options();
839 $skin_options = fckeditor_load_skin_options();
840 $lang_options = fckeditor_load_lang_options();
841
842 // because the settings are saved as strings we need to test for the string 'true'
843 if ($profile->settings['allow_user_conf'] == 't') {
844 $form['fckeditor'] = array(
845 '#type' => 'fieldset',
846 '#title' => t('Rich Text Editor settings'),
847 '#weight' => 10,
848 '#collapsible' => TRUE,
849 '#collapsed' => TRUE
850 );
851
852 $form['fckeditor']['fckeditor_default'] = array(
853 '#type' => 'select',
854 '#title' => t('Default state'),
855 '#default_value' => isset($user->fckeditor_default) ? $user->fckeditor_default : (isset($profile->settings['default']) ? $profile->settings['default'] : 'f'),
856 '#options' => array('t' => t('enabled'), 'f' => t('disabled')),
857 '#description' => t('Should rich-text editing be enabled or disabled by default in textarea fields? If disabled, rich text editor may still be enabled using toggle or popup window.'),
858 );
859
860 $form['fckeditor']['fckeditor_show_toggle'] = array(
861 '#type' => 'select',
862 '#title' => t('Show disable/enable rich text editor toggle'),
863 '#default_value' => isset($user->fckeditor_show_toggle) ? $user->fckeditor_show_toggle : (isset($profile->settings['show_toggle']) ? $profile->settings['show_toggle'] : 't'),
864 '#options' => array('t' => t('true'), 'f' => t('false')),
865 '#description' => t('Whether or not to show the disable/enable rich text editor toggle below the textarea. Works only if FCKeditor is not running a popup window (see below).'),
866 );
867
868 $form['fckeditor']['fckeditor_popup'] = array(
869 '#type' => 'select',
870 '#title' => t('Use FCKeditor in a popup window'),
871 '#default_value' => isset($user->fckeditor_popup) ? $user->fckeditor_popup : (isset($profile->settings['popup']) ? $profile->settings['popup'] : 'f'),
872 '#options' => array('f' => t('false'), 't' => t('true')),
873 '#description' => t('If this option is enabled a link to a popup window will be used instead of a textarea replace.'),
874 );
875
876 $form['fckeditor']['fckeditor_skin'] = array(
877 '#type' => 'select',
878 '#title' => t('Skin'),
879 '#default_value' => isset($user->fckeditor_skin) ? $user->fckeditor_skin : (isset($profile->settings['skin']) ? $profile->settings['skin'] : 'default'),
880 '#options' => $skin_options,
881 '#description' => t('Choose a FCKeditor skin.'),
882 );
883
884 $form['fckeditor']['fckeditor_toolbar'] = array(
885 '#type' => 'select',
886 '#title' => t('Toolbar'),
887 '#default_value' => isset($user->fckeditor_toolbar) ? $user->fckeditor_toolbar : (isset($profile->settings['toolbar']) ? $profile->settings['toolbar'] : 'default'),
888 '#options' => $toolbar_options,
889 '#description' => t('Choose a FCKeditor toolbar set.'),
890 );
891
892 $form['fckeditor']['fckeditor_expand'] = array(
893 '#type' => 'select',
894 '#title' => t('Start the toolbar expanded'),
895 '#default_value' => isset($user->fckeditor_expand) ? $user->fckeditor_expand : (isset($profile->settings['expand']) ? $profile->settings['expand'] : 't'),
896 '#options' => array('t' => t('enabled'), 'f' => t('disabled')),
897 '#description' => t('The toolbar start expanded or collapsed.'),
898 );
899
900 $form['fckeditor']['fckeditor_width'] = array(
901 '#type' => 'textfield',
902 '#title' => t('Width'),
903 '#default_value' => isset($user->fckeditor_width) ? $user->fckeditor_width : (isset($profile->settings['width']) ? $profile->settings['width'] : '100%'),
904 '#description' => t("Width in pixels or percent. Ex: 400 or 100%"),
905 '#size' => 40,
906 '#maxlength' => 128,
907 );
908
909 $form['fckeditor']['fckeditor_lang'] = array(
910 '#type' => 'select',
911 '#title' => t('Language'),
912 '#default_value' => isset($user->fckeditor_lang) ? $user->fckeditor_lang : (isset($profile->settings['lang']) ? $profile->settings['lang'] : 'en'),
913 '#options' => $lang_options,
914 '#description' => t('The language for the FCKeditor interface.')
915 );
916
917 $form['fckeditor']['fckeditor_auto_lang'] = array(
918 '#type' => 'select',
919 '#title' => t('Auto-detect language'),
920 '#default_value' => isset($user->fckeditor_auto_lang) ? $user->fckeditor_auto_lang : (isset($profile->settings['auto_lang']) ? $profile->settings['auto_lang'] : 't'),
921 '#options' => array('t' => t('true'), 'f' => t('false')),
922 '#description' => t('Use auto detect user language feature.')
923 );
924
925 return array('fckeditor' => $form);
926 }
927 }
928
929 if ($type == 'validate') {
930 return array(
931 'fckeditor_default' => $edit['fckeditor_default'],
932 'fckeditor_show_toggle' => $edit['fckeditor_show_toggle'],
933 'fckeditor_popup' => $edit['fckeditor_popup'],
934 'fckeditor_skin' => $edit['fckeditor_skin'],
935 'fckeditor_toolbar' => $edit['fckeditor_toolbar'],
936 'fckeditor_expand' => $edit['fckeditor_expand'],
937 'fckeditor_width' => $edit['fckeditor_width'],
938 'fckeditor_lang' => $edit['fckeditor_lang'],
939 'fckeditor_auto_lang' => $edit['fckeditor_auto_lang'],
940 );
941 }
942 }
943
944 /**
945 * Return an HTML form for profile configuration.
946 */
947 function fckeditor_profile_form($edit) {
948
949 $output .= drupal_get_form('fckeditor_profile_form_build', $edit);
950
951 return $output;
952 }
953
954 /**
955 * Return an HTML form for global profile configuration.
956 */
957 function fckeditor_global_profile_form($edit) {
958
959 $output .= drupal_get_form('fckeditor_global_profile_form_build', $edit);
960
961 return $output;
962 }
963
964 function fckeditor_load_toolbar_options() {
965 $arr = array();
966 $module_drupal_path = drupal_get_path('module', 'fckeditor');
967 $fckconfig_js = $module_drupal_path .'/fckeditor/fckconfig.js';
968 $fckeditor_config_js = $module_drupal_path .'/fckeditor.config.js';
969 if (file_exists($fckconfig_js) && is_readable($fckconfig_js)) {
970 $fp = @fopen($fckconfig_js, "r");
971 if ($fp) {
972 while (!feof($fp)) {
973 $line = fgets($fp, 1024);
974 if (preg_match("/FCKConfig\.ToolbarSets\[(\"|')(.*?)\\1\]/i", $line, $matches)) {
975 $arr[$matches[2]] = ucfirst($matches[2]);
976 }
977 }
978 fclose($fp);
979 }
980 }