Media directory instructions added
[project/fckeditor.git] / fckeditor.module
CommitLineData
04b827fa 1<?php
e44c2389 2// $Id$
3/**
4 * @file
f3d88ca0 5 * FCKeditor Module for Drupal 4.7
ebc6fdec 6 *
e44c2389 7 * This module allows Drupal to replace textarea fields with the FCKeditor.
8 * This HTML text editor brings many of the powerful functionalities of
9 * known desktop editors like Word to the web. It's relatively lightweight
10 * and doesn't require any kind of installation on the client computer.
f3d88ca0 11 *
12 * ----------------------------------------------------------------------------
04b827fa 13 * FCKeditor - The text editor for internet
f3d88ca0 14 * Copyright (C) 2003-2006 Frederico Caldeira Knabben
ebc6fdec 15 *
04b827fa 16 * Licensed under the terms of the GNU Lesser General Public License:
f3d88ca0 17 * http://www.opensource.org/licenses/lgpl-license.php
ebc6fdec 18 *
04b827fa 19 * For further information visit:
f3d88ca0 20 * http://www.fckeditor.net/
f3d88ca0 21 * ----------------------------------------------------------------------------
04b827fa
DS
22 *
23 * @version 1.0
24 * @author LatPro Inc (George)
f3d88ca0 25 * @version 1.1
26 * @author Frederico Caldeira Knabben (www.fckeditor.net)
27 * @version 1.2
28 * @author Ontwerpwerk (www.ontwerpwerk.nl)
04b827fa
DS
29 */
30
31
32/**
33 * Implementation of hook_help
34 */
35function fckeditor_help($section = '') {
e44c2389 36 switch($section) {
37 case 'admin/modules#name':
38 $output = t("FCKeditor");
39 break;
40 case 'admin/modules#description':
41 $output = t("Enables the usage of FCKeditor (WYSIWYG editor) instead of plain text fields.");
42 break;
43 case 'admin/help#fckeditor':
44 $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>
ccd18229 45<p>More information is located at the %fckeditorlink. A small user guide is located at %userguidelink.</p>", array('%fckeditorlink'=>l(t('FCKeditor homepage'), 'http://www.fckeditor.net'), '%userguidelink'=>l(t('FCKeditor userguide'), 'http://wiki.fckeditor.net/UsersGuide')));
92b2e6cf 46 $output .= t('<h3>Security</h3>
47<p>Note that enabling file uploads is a security risk, please take care about to who and when you will grant access.</p>');
e44c2389 48 // the rest is untranslated for the moment
b683d2b1 49 $output .= "<h3>How to enable the file browser (in FCKeditor 2.3.x)</h3>
e44c2389 50<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>
51<p>To enable file browsing you need to edit the connector configuration file in your fckeditor module directory, the file should be in:<br /><code>/fckeditor/editor/filemanager/browser/default/connectors/php/config.php</code></p>
ccd18229 52<p>In this file you will need to enable the file browser:<br /><code>$ Config['Enabled'] = true;</code></p>
53<p>To use the drupal files directory you also need to comment out the following line in the connector configuration:<br /><code>//$ Config['UserFilesPath'] = '/UserFiles/';</code></p>
e2610d9c 54<p>Furthermore, you will need to create a <em>'File'</em>, <em>'Image'</em>, <em>'Flash'</em> and <em>'Media'</em> subdirectory in your drupal files directory ('".file_directory_path()."'). These directories must have the same privileges as the drupal files directory. In some cases these directories must be world writable (chmod 0777).</p>";
e44c2389 55 break;
04b827fa
DS
56 }
57 return $output;
58}
59
60
61/**
62 * Implementation of hook_perm
63 */
64function fckeditor_perm() {
92b2e6cf 65 return array('use default fckeditor', 'use advanced fckeditor', 'allow fckeditor file uploads');
04b827fa
DS
66}
67
04b827fa 68/**
e44c2389 69 * Implementation of hook_elelments
70 *
71 * Adds an extra procession instruction to the form rendering for textareas
72 *
73 * @return $type
74 * Additional array for the element configuration
04b827fa 75 */
f3d88ca0 76function fckeditor_elements() {
77 $type = array();
ebc6fdec 78 if (user_access('use advanced fckeditor') || user_access('use default fckeditor')) {
f3d88ca0 79 // only roles with permission get the fckeditor
80 if (fckeditor_is_compatible_client()) {
81 // it would be useless to dig deeper if we're not able or allowed to
82 $type['textarea'] = array(
83 '#process' => array(
84 'fckeditor_process_textarea' => array()
85 ),
86 );
04b827fa
DS
87 }
88 }
f3d88ca0 89 return $type;
04b827fa
DS
90}
91
04b827fa
DS
92/**
93 * Implementation of hook_setting().
e44c2389 94 *
95 * Configuration for the FCKeditor module
04b827fa
DS
96 */
97function fckeditor_settings() {
f3d88ca0 98 // Settings form
e44c2389 99 $toolbar_options = array(
100 'Default' => 'Default',
101 'DrupalFull' => 'Drupal Full',
102 'DrupalBasic' => 'Drupal Basic',
103 'Basic' => 'Basic',
104 );
ebc6fdec 105
f3d88ca0 106 // Generate the form - settings applying to all patterns first
107 $form['fckeditor_settings'] = array(
108 '#type' => 'fieldset',
109 '#weight' => -20,
110 '#title' => t('Basic settings'),
111 '#collapsible' => TRUE,
e44c2389 112 '#collapsed' => FALSE,
f3d88ca0 113 );
e44c2389 114
115 $form['fckeditor_settings']['fckeditor_popup'] = array(
116 '#type' => 'checkbox',
117 '#title' => t('Use FCKeditor in a popup window'),
118 '#default_value' => variable_get('fckeditor_popup', '0'),
119 '#description' => t('If this option is selected a link to a popup window will be used instead of a textarea replace.'),
120 );
121
f3d88ca0 122 $form['fckeditor_settings']['fckeditor_default_toolbar'] = array(
123 '#type' => 'select',
124 '#title' => t('Default Toolbar'),
125 '#default_value' => variable_get('fckeditor_default_toolbar', 'DrupalBasic'),
126 '#options' => $toolbar_options,
127 '#description' => t('Choose a default toolbar set.'),
128 );
e44c2389 129
f3d88ca0 130 $form['fckeditor_settings']['fckeditor_advanced_toolbar'] = array(
131 '#type' => 'select',
132 '#title' => t('Advanced Toolbar'),
133 '#default_value' => variable_get('fckeditor_advanced_toolbar', 'DrupalFull'),
134 '#options' => $toolbar_options,
135 '#description' => t('Choose a toolbar set for administrators.'),
136 );
04b827fa 137
f3d88ca0 138 $form['fckeditor_exclude_settings'] = array(
139 '#type' => 'fieldset',
140 '#weight' => -15,
141 '#title' => t('Exclusion settings'),
142 '#collapsible' => TRUE,
143 '#collapsed' => TRUE,
144 );
e44c2389 145
f3d88ca0 146 $form['fckeditor_exclude_settings']['fckeditor_minimum_rows'] = array(
147 '#type' => 'textfield',
148 '#title' => t('Minimum rows'),
149 '#default_value' => variable_get('fckeditor_minimum_rows', 5),
e44c2389 150 '#description' => t("Textareas must have a minimum of rows before FCKeditor will be triggered. Enter '1' if you do not want to use this feature."),
f3d88ca0 151 );
e44c2389 152
153 /**
154 * get excluded fields - so we can have normal textareas too
155 * split the phrase by any number of commas or space characters,
156 * which include " ", \r, \t, \n and \f
157 */
f3d88ca0 158 $form['fckeditor_exclude_settings']['fckeditor_exclude'] = array(
159 '#type' => 'textarea',
ccd18229 160 '#title' => t('Exclude fields'),
f3d88ca0 161 '#cols' => 60,
162 '#rows' => 5,
163 '#default_value' => variable_get("fckeditor_exclude", ''),
164 '#description' => t("Names (HTML ID's) of fields that may not have an FCKeditor (separated by commas, spaces or newlines. You may also use * for a wildcard)"),
165 );
166
167 $form['fckeditor_special_settings'] = array(
168 '#type' => 'fieldset',
169 '#weight' => -10,
170 '#title' => t('Advanced settings'),
171 '#collapsible' => TRUE,
172 '#collapsed' => TRUE,
173 );
e44c2389 174
f3d88ca0 175 $form['fckeditor_special_settings']['fckeditor_toolbar_start_expanded'] = array(
176 '#type' => 'checkbox',
177 '#title' => t('Start the toolbar expanded'),
178 '#default_value' => variable_get('fckeditor_toolbar_start_expanded', '1'),
179 '#description' => t('The toolbar start expanded or collapsed.'),
180 );
e44c2389 181
f3d88ca0 182 $form['fckeditor_special_settings']['fckeditor_width'] = array(
183 '#type' => 'textfield',
184 '#title' => t('Width'),
185 '#default_value' => variable_get("fckeditor_width", "100%"),
9286dec5 186 '#description' => t("Width in pixels or percent. Ex: 400 or 100%"),
f3d88ca0 187 );
188
e44c2389 189 // People might want other skins, but lets be evil and not let them have them that easy
f3d88ca0 190 $form['fckeditor_skin'] = array('#type' => 'value', '#value' => variable_get('fckeditor_skin', 'default'));
191
192 return $form;
ebc6fdec 193}
04b827fa
DS
194
195
196/**
9286dec5 197 * This function create the HTML objects required for the FCKeditor
e44c2389 198 *
199 * @param $element
200 * A fully populated form elment to add the editor to
201 * @return
202 * The same $element with extra FCKeditor markup and initialization
04b827fa 203 */
f3d88ca0 204function fckeditor_process_textarea($element) {
205 $exclude = preg_split("/[\s,]+/", strip_tags(variable_get("fckeditor_exclude", '')));
206
ccd18229 207 if (($element['#rows'] > variable_get('fckeditor_minimum_rows', 5))
23824481 208 && !fckeditor_idsearch($element['#id'], $exclude)) {
e44c2389 209 // only replace textarea when it has enough rows and it is not in the exclusion list
f3d88ca0 210
211 // setting some variables
25f91b44 212 $module_drupal_path = drupal_get_path('module', 'fckeditor');
213 $module_full_path = base_path() . $module_drupal_path;
e2610d9c 214 // get the default drupal files path
215 $files_path = file_directory_path();
e44c2389 216 // '-' in a javascript id will not work
f3d88ca0 217 $js_id = 'oFCKeditor_' . str_replace('-', '_', $element['#id']);
218
219 // configured in settings
220 $width = variable_get("fckeditor_width", '100%');
221
222 // sensible default for small toolbars
e44c2389 223 $height = $element['#rows'] * 14 + 100;
f3d88ca0 224
225 // nessecary because FCKeditor interferes with resize script
226 $element['#resizable'] = FALSE;
227
25f91b44 228 drupal_add_js($module_drupal_path . '/fckeditor/fckeditor.js');
f3d88ca0 229
230 if (user_access('use advanced fckeditor')) {
231 $toolbar = variable_get("fckeditor_advanced_toolbar", 'DrupalFull');
232 $height += 100; // sensible default for admin toolbars toolbars
e44c2389 233 }
234 else {
f3d88ca0 235 $toolbar = variable_get("fckeditor_default_toolbar", 'DrupalBasic');
236 }
237
e44c2389 238 $element['#suffix'] .= "\n<script type=\"text/javascript\">
f3d88ca0 239var ".$js_id." = new FCKeditor( '".$element['#id']."' );
25f91b44 240".$js_id.".BasePath = '".$module_full_path."/fckeditor/';
241".$js_id.".Config['CustomConfigurationsPath'] = '".$module_full_path."/fckeditor.config.js';
f3d88ca0 242".$js_id.".ToolbarSet = '".$toolbar."';
92b2e6cf 243".$js_id.".Height = '".$height."';\n";
e44c2389 244
245 // add code for filebrowser for users that have access
92b2e6cf 246 if (user_access('allow fckeditor file uploads')) {
e2610d9c 247 $element['#suffix'] .= $js_id.".Config['LinkBrowserURL'] = '".$module_full_path."/fckeditor/editor/filemanager/browser/default/browser.html?Connector=connectors/php/connector.php&ServerPath=/".$files_path."';
248".$js_id.".Config['ImageBrowserURL'] = '".$module_full_path."/fckeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=connectors/php/connector.php&ServerPath=/".$files_path."';
249".$js_id.".Config['FlashBrowserURL'] = '".$module_full_path."/fckeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/php/connector.php&ServerPath=/".$files_path."';
92b2e6cf 250".$js_id.".Config['LinkUpload'] = false;
251".$js_id.".Config['ImageUpload'] = false;
252".$js_id.".Config['FlashUpload'] = false;\n";
253 } else {
254 $element['#suffix'] .= $js_id.".Config['LinkBrowser'] = false;
255".$js_id.".Config['ImageBrowser'] = false;
256".$js_id.".Config['FlashBrowser'] = false;
257".$js_id.".Config['LinkUpload'] = false;
258".$js_id.".Config['ImageUpload'] = false;
259".$js_id.".Config['FlashUpload'] = false;\n";
260 }
e44c2389 261
92b2e6cf 262 $element['#suffix'] .= "</script>\n";
f3d88ca0 263
264 if (variable_get('fckeditor_popup', '0')) {
265 // Add the script file with the popup open function.
25f91b44 266 drupal_add_js($module_drupal_path . '/fckeditor.popup.js');
e44c2389 267 $element['#title'] .= " <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>";
268 }
269 else {
f3d88ca0 270 // if no popup mode, add the editor
e44c2389 271 $element['#suffix'] .="<script type=\"text/javascript\">
f3d88ca0 272 ".$js_id.".ReplaceTextarea();
92b2e6cf 273</script>\n";
f3d88ca0 274 }
275 }
f3d88ca0 276 return $element;
04b827fa
DS
277}
278
23824481 279
280/**
e44c2389 281 * Search the field id for matches in array of matches
282 *
283 * @param $search
284 * A string representing a form field id
285 * @ param $array
286 * An $array with strings to match the $search parameter against
287 *
288 * @return
289 * TRUE on match, FALSE on no match
23824481 290 */
291function fckeditor_idsearch($search, $array) {
292 foreach ($array as $key => $value) {
293 if (!empty($value) && preg_match('/^'.str_replace('*','.*',$value).'$/i', $search)) {
294 // on any first match we know we're done here so return positive
295 return true;
f3d88ca0 296 }
f3d88ca0 297 }
23824481 298 return false;
f3d88ca0 299}
04b827fa 300
23824481 301
04b827fa 302/**
e44c2389 303 * Test if client can render the FCKeditor
304 *
305 * Check the user agent for a matching browser,
306 * using HTTP_USER_AGENT because the browsers that are known to support FCKeditor are limited
307 *
308 * @return
309 * TRUE if the browser is reasonably capable
04b827fa
DS
310 */
311function fckeditor_is_compatible_client() {
e44c2389 312 $useragent = $_SERVER['HTTP_USER_AGENT'];
ebc6fdec 313
e44c2389 314 if (strpos($useragent, 'MSIE') !== false && strpos($useragent, 'mac') === false && strpos($useragent, 'Opera') === false) {
315 $browserversion = (int)substr($useragent, strpos($useragent, 'MSIE') + 5, 3);
316 return ($browserversion >= 5.5);
04b827fa 317 }
ccd18229 318 elseif (strpos($useragent, 'Gecko') !== false) {
e44c2389 319 $browserversion = (int)substr($useragent, strpos($useragent, 'Gecko/') + 6, 8);
320 return ($browserversion >= 20030210);
04b827fa
DS
321 }
322 else
323 return false;
324}