* Use the TinyMCE WYSIWYG editor for editing your Drupal site. A collaborative modul...
[project/tinymce.git] / tinymce.module
1 <?php
2 // $Id$
3 // A collaborative project by Matt Westgate <drupal at asitis dot org>
4 // and Richard Bennett <richard.b@gritechnologies.com>
5
6 /**
7 * @file
8 * Integrate the TinyMCE editor (http://tinymce.moxiecode.com/) into Drupal.
9 */
10
11 /**
12 * Implementation of hook_menu().
13 *
14 * Add the JavaScript file to the page head. Doing this in a menu hook is a
15 * little less expensive that in *_init since we don't need to load the head for
16 * Drupal-cached pages.
17 *
18 */
19 function tinymce_menu($may_cache) {
20 if (!$may_cache) {
21 drupal_set_html_head('<script language="javascript" type="text/javascript" src="'. drupal_get_path('module', 'tinymce') .'/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>');
22 }
23 }
24
25 /**
26 * Implementation of hook_help().
27 */
28 function tinymce_help($section) {
29 switch ($section) {
30 case 'admin/modules#description':
31 return t('The TinyMCE Javascript HTML WYSIWYG editor.');
32
33 case 'admin/settings/tinymce#pages':
34 return "node/*\nuser/*\ncomment/*";
35 }
36 }
37
38 /**
39 * Implementation of hook_perm().
40 */
41 function tinymce_perm() {
42 return array('use tinymce');
43 }
44
45 /**
46 * Implementation of hook_settings().
47 */
48 function tinymce_settings() {
49 drupal_set_title(t('TinyMCE settings'));
50 $group = form_radios(t('Default theme'), 'tinymce_theme', variable_get('tinymce_theme', 'default'), _tinymce_get_themes());
51 $output = form_group('', $group);
52
53 $group = form_radios(t('Use TinyMCE'), 'tinymce_all', variable_get('tinymce_all', 1), array(t('on specific pages'), t('on all textareas')));
54 if (!variable_get('tinymce_all', 1)) {
55 $group .= form_textarea(t('Pages'), 'tinymce_pages', variable_get('tinymce_pages', tinymce_help('admin/settings/tinymce#pages')), 40, 5, t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are '<em>blog</em>' for the blog page and '<em>blog/*</em>' for every personal blog. '<em>&lt;front&gt;</em>' is the front page."));
56 }
57 $output .= form_group('', $group);
58 return $output;
59 }
60
61 function tinymce_textarea($op, $name) {
62 if (!user_access('use tinymce')) return NULL;
63
64 global $user;
65 $theme_name = $user->tinymce_theme ? $user->tinymce_theme : variable_get('tinymce_theme', 'default');
66
67 if ($op == 'pre' && _tinymce_page_match() && $user->tinymce_status) {
68 global $base_url;
69
70 $output = <<<EOD
71 <script language="javascript" type="text/javascript">
72 tinyMCE.init({
73 mode : "textareas",
74 theme : "$theme_name",
75 document_base_url : "$base_url/"
76 });
77 </script>
78 EOD;
79
80 return $output;
81 }
82 }
83
84 /**
85 * Implementation of hook_user().
86 */
87 function tinymce_user($type, &$edit, &$user, $category = NULL) {
88 if ($type == 'form' && $category == 'account' && user_access('use tinymce')) {
89 $form = form_radios(t('Use TinyMCE'), 'tinymce_status', $edit['tinymce_status'], array(t('Disabled'), t('Enabled')));
90 if ($edit['tinymce_status']) {
91 $form .= form_radios(t('Default theme'), 'tinymce_theme', $edit['tinymce_theme'] ? $edit['tinymce_theme'] : variable_get('tinymce_theme', 'default'), _tinymce_get_themes());
92 }
93 else {
94 $form .= form_hidden('tinymce_theme', $edit['tinymce_theme']);
95 }
96 return array(array('title' => t('TinyMCE settings'), 'data' => $form));
97 }
98 if ($type == 'validate') {
99 // validate user data editing
100 return array('tinymce_theme' => $edit['tinymce_theme'], 'tinymce_status' => $edit['tinymce_status']);
101 }
102 }
103
104 /**
105 * Grab the themes available to TinyMCE.
106 *
107 * TinyMCE themes control the functionality and buttons that are available to a
108 * user. Themes are only looked for within the default TinyMCE theme directory.
109 *
110 * @return
111 * An array of theme names.
112 */
113 function _tinymce_get_themes() {
114 static $themes = array();
115
116 if (!$themes) {
117 $theme_loc = drupal_get_path('module', 'tinymce') .'/tinymce/jscripts/tiny_mce/themes/';
118 if (is_dir($theme_loc) && $dh = opendir($theme_loc)) {
119 while (($file = readdir($dh)) !== false) {
120 if ($file != '.' && $file != '..' && is_dir($theme_loc . $file)) {
121 $themes[$file] = $file;
122 }
123 }
124 closedir($dh);
125 asort($themes);
126 }
127 }
128
129 return $themes;
130 }
131
132 /**
133 * Determine if TinyMCE can render the current page.
134 *
135 * @return
136 * TRUE if can render, FALSE if not allowed.
137 */
138 function _tinymce_page_match() {
139 $edit = $_POST['edit'];
140
141 //Kill TinyMCE if we're editing a textarea with PHP in it!
142 if ($edit) {
143 if ($edit['format'] == 2) {
144 return FALSE;
145 }
146 }
147 else {
148 // PHP input formats are #2 in the filters table.
149 preg_match("|^node/(\d+)(/edit)$|", $_GET['q'], $match);
150 if (intval($match[1]) > 0) {
151 if (db_result(db_query('SELECT format FROM {node} WHERE nid = %d AND format = 2', $match[1]))) {
152 return FALSE;
153 }
154 }
155 }
156
157 if (variable_get('tinymce_all', 1)) {
158 return TRUE;
159 }
160 else {
161 $page_match = FALSE;
162 $pages = variable_get('tinymce_pages', tinymce_help('admin/settings/tinymce#pages'));
163 if ($pages) {
164 $path = drupal_get_path_alias($_GET['q']);
165 $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. variable_get('site_frontpage', 'node') .'\2'), preg_quote($pages, '/')) .')$/';
166 $page_match = preg_match($regexp, $path);
167 }
168 return $page_match;
169 }
170 }
171 ?>