]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/class-wp-editor.php
Wordpress 3.3.1-scripts
[autoinstalls/wordpress.git] / wp-includes / class-wp-editor.php
1 <?php
2 /**
3  * Facilitates adding of the WordPress editor as used on the Write and Edit screens.
4  *
5  * @package WordPress
6  * @since 3.3
7  *
8  * Private, not included by default. See wp_editor() in wp-includes/general-template.php.
9  */
10
11 final class _WP_Editors {
12         public static $mce_locale;
13
14         private static $mce_settings = array();
15         private static $qt_settings = array();
16         private static $plugins = array();
17         private static $qt_buttons = array();
18         private static $ext_plugins;
19         private static $baseurl;
20         private static $first_init;
21         private static $this_tinymce = false;
22         private static $this_quicktags = false;
23         private static $has_tinymce = false;
24         private static $has_quicktags = false;
25         private static $has_medialib = false;
26         private static $editor_buttons_css = true;
27
28         private function __construct() {}
29
30         public static function parse_settings($editor_id, $settings) {
31                 $set = wp_parse_args( $settings,  array(
32                         'wpautop' => true, // use wpautop?
33                         'media_buttons' => true, // show insert/upload button(s)
34                         'textarea_name' => $editor_id, // set the textarea name to something different, square brackets [] can be used here
35                         'textarea_rows' => get_option('default_post_edit_rows', 10), // rows="..."
36                         'tabindex' => '',
37                         'editor_css' => '', // intended for extra styles for both visual and HTML editors buttons, needs to include the <style> tags, can use "scoped".
38                         'editor_class' => '', // add extra class(es) to the editor textarea
39                         'teeny' => false, // output the minimal editor config used in Press This
40                         'dfw' => false, // replace the default fullscreen with DFW (needs specific DOM elements and css)
41                         'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array()
42                         'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
43                 ) );
44
45                 self::$this_tinymce = ( $set['tinymce'] && user_can_richedit() );
46                 self::$this_quicktags = (bool) $set['quicktags'];
47
48                 if ( self::$this_tinymce )
49                         self::$has_tinymce = true;
50
51                 if ( self::$this_quicktags )
52                         self::$has_quicktags = true;
53
54                 return $set;
55         }
56
57         /**
58          * Outputs the HTML for a single instance of the editor.
59          *
60          * @param string $content The initial content of the editor.
61          * @param string $editor_id ID for the textarea and TinyMCE and Quicktags instances (can contain only ASCII letters and numbers).
62          * @param array $settings See the _parse_settings() method for description.
63          */
64         public static function editor( $content, $editor_id, $settings = array() ) {
65
66                 $set = self::parse_settings($editor_id, $settings);
67                 $editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"';
68                 $tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
69                 $rows = ' rows="' . (int) $set['textarea_rows'] . '"';
70                 $switch_class = 'html-active';
71                 $toolbar = $buttons = '';
72
73                 if ( !current_user_can( 'upload_files' ) )
74                         $set['media_buttons'] = false;
75
76                 if ( self::$this_quicktags && self::$this_tinymce ) {
77                         $switch_class = 'html-active';
78
79                         if ( 'html' == wp_default_editor() ) {
80                                 add_filter('the_editor_content', 'wp_htmledit_pre');
81                         } else {
82                                 add_filter('the_editor_content', 'wp_richedit_pre');
83                                 $switch_class = 'tmce-active';
84                         }
85
86                         $buttons .= '<a id="' . $editor_id . '-html" class="hide-if-no-js wp-switch-editor switch-html" onclick="switchEditors.switchto(this);">' . __('HTML') . "</a>\n";
87                         $buttons .= '<a id="' . $editor_id . '-tmce" class="hide-if-no-js wp-switch-editor switch-tmce" onclick="switchEditors.switchto(this);">' . __('Visual') . "</a>\n";
88                 }
89
90                 echo '<div id="wp-' . $editor_id . '-wrap" class="wp-editor-wrap ' . $switch_class . '">';
91
92                 if ( self::$editor_buttons_css ) {
93                         wp_print_styles('editor-buttons');
94                         self::$editor_buttons_css = false;
95                 }
96
97                 if ( !empty($set['editor_css']) )
98                         echo $set['editor_css'] . "\n";
99
100                 if ( !empty($buttons) || $set['media_buttons'] ) {
101                         echo '<div id="wp-' . $editor_id . '-editor-tools" class="wp-editor-tools">';
102                         echo $buttons;
103
104                         if ( $set['media_buttons'] ) {
105                                 self::$has_medialib = true;
106
107                                 if ( !function_exists('media_buttons') )
108                                         include(ABSPATH . 'wp-admin/includes/media.php');
109
110                                 echo '<div id="wp-' . $editor_id . '-media-buttons" class="hide-if-no-js wp-media-buttons">';
111                                 do_action('media_buttons', $editor_id);
112                                 echo "</div>\n";
113                         }
114                         echo "</div>\n";
115                 }
116
117                 $the_editor = apply_filters('the_editor', '<div id="wp-' . $editor_id . '-editor-container" class="wp-editor-container"><textarea' . $editor_class . $rows . $tabindex . ' cols="40" name="' . $set['textarea_name'] . '" id="' . $editor_id . '">%s</textarea></div>');
118                 $content = apply_filters('the_editor_content', $content);
119
120                 printf($the_editor, $content);
121                 echo "\n</div>\n\n";
122
123                 self::editor_settings($editor_id, $set);
124         }
125
126         public static function editor_settings($editor_id, $set) {
127                 global $editor_styles;
128                 $first_run = false;
129
130                 if ( empty(self::$first_init) ) {
131                         if ( is_admin() ) {
132                                 add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_js'), 50 );
133                                 add_action( 'admin_footer', array( __CLASS__, 'enqueue_scripts'), 1 );
134                         } else {
135                                 add_action( 'wp_print_footer_scripts', array( __CLASS__, 'editor_js'), 50 );
136                                 add_action( 'wp_footer', array( __CLASS__, 'enqueue_scripts'), 1 );
137                         }
138                 }
139
140                 if ( self::$this_quicktags ) {
141
142                         $qtInit = array(
143                                 'id' => $editor_id,
144                                 'buttons' => ''
145                         );
146
147                         if ( is_array($set['quicktags']) )
148                                 $qtInit = array_merge($qtInit, $set['quicktags']);
149
150                         if ( empty($qtInit['buttons']) )
151                                 $qtInit['buttons'] = 'strong,em,link,block,del,ins,img,ul,ol,li,code,more,spell,close';
152
153                         if ( $set['dfw'] )
154                                 $qtInit['buttons'] .= ',fullscreen';
155
156                         $qtInit = apply_filters('quicktags_settings', $qtInit, $editor_id);
157                         self::$qt_settings[$editor_id] = $qtInit;
158
159                         self::$qt_buttons = array_merge( self::$qt_buttons, explode(',', $qtInit['buttons']) );
160                 }
161
162                 if ( self::$this_tinymce ) {
163
164                         if ( empty(self::$first_init) ) {
165                                 self::$baseurl = includes_url('js/tinymce');
166                                 self::$mce_locale = $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
167                                 $no_captions = (bool) apply_filters( 'disable_captions', '' );
168                                 $plugins = array( 'inlinepopups', 'spellchecker', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs' );
169                                 $first_run = true;
170
171                                 if ( $set['teeny'] ) {
172                                         self::$plugins = $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs'), $editor_id );
173                                         $ext_plugins = '';
174                                 } else {
175                                         /*
176                                         The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
177                                         It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
178                                         The url should be absolute and should include the js file name to be loaded. Example:
179                                         array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
180                                         If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
181                                         */
182                                         $mce_external_plugins = apply_filters('mce_external_plugins', array());
183
184                                         $ext_plugins = '';
185                                         if ( ! empty($mce_external_plugins) ) {
186
187                                                 /*
188                                                 The following filter loads external language files for TinyMCE plugins.
189                                                 It takes an associative array 'plugin_name' => 'path', where path is the
190                                                 include path to the file. The language file should follow the same format as
191                                                 /tinymce/langs/wp-langs.php and should define a variable $strings that
192                                                 holds all translated strings.
193                                                 When this filter is not used, the function will try to load {mce_locale}.js.
194                                                 If that is not found, en.js will be tried next.
195                                                 */
196                                                 $mce_external_languages = apply_filters('mce_external_languages', array());
197
198                                                 $loaded_langs = array();
199                                                 $strings = '';
200
201                                                 if ( ! empty($mce_external_languages) ) {
202                                                         foreach ( $mce_external_languages as $name => $path ) {
203                                                                 if ( @is_file($path) && @is_readable($path) ) {
204                                                                         include_once($path);
205                                                                         $ext_plugins .= $strings . "\n";
206                                                                         $loaded_langs[] = $name;
207                                                                 }
208                                                         }
209                                                 }
210
211                                                 foreach ( $mce_external_plugins as $name => $url ) {
212
213                                                         if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
214
215                                                         $plugins[] = '-' . $name;
216
217                                                         $plugurl = dirname($url);
218                                                         $strings = $str1 = $str2 = '';
219                                                         if ( ! in_array($name, $loaded_langs) ) {
220                                                                 $path = str_replace( content_url(), '', $plugurl );
221                                                                 $path = WP_CONTENT_DIR . $path . '/langs/';
222
223                                                                 if ( function_exists('realpath') )
224                                                                         $path = trailingslashit( realpath($path) );
225
226                                                                 if ( @is_file($path . $mce_locale . '.js') )
227                                                                         $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
228
229                                                                 if ( @is_file($path . $mce_locale . '_dlg.js') )
230                                                                         $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
231
232                                                                 if ( 'en' != $mce_locale && empty($strings) ) {
233                                                                         if ( @is_file($path . 'en.js') ) {
234                                                                                 $str1 = @file_get_contents($path . 'en.js');
235                                                                                 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
236                                                                         }
237
238                                                                         if ( @is_file($path . 'en_dlg.js') ) {
239                                                                                 $str2 = @file_get_contents($path . 'en_dlg.js');
240                                                                                 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
241                                                                         }
242                                                                 }
243
244                                                                 if ( ! empty($strings) )
245                                                                         $ext_plugins .= "\n" . $strings . "\n";
246                                                         }
247
248                                                         $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
249                                                         $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
250
251                                                         self::$ext_plugins .= $ext_plugins;
252                                                 }
253                                         }
254
255                                         $plugins = array_unique( apply_filters('tiny_mce_plugins', $plugins) );
256                                 }
257
258                                 if ( $set['dfw'] )
259                                         $plugins[] = 'wpfullscreen';
260
261                                 self::$plugins = $plugins;
262
263                                 /*
264                                 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
265                                 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
266                                 The + sign marks the default language. More information:
267                                 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
268                                 */
269                                 $mce_spellchecker_languages = apply_filters('mce_spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv');
270
271                                 self::$first_init = array(
272                                         'mode' => 'exact',
273                                         'width' => '100%',
274                                         'theme' => 'advanced',
275                                         'skin' => 'wp_theme',
276                                         'language' => self::$mce_locale,
277                                         'spellchecker_languages' => $mce_spellchecker_languages,
278                                         'theme_advanced_toolbar_location' => 'top',
279                                         'theme_advanced_toolbar_align' => 'left',
280                                         'theme_advanced_statusbar_location' => 'bottom',
281                                         'theme_advanced_resizing' => true,
282                                         'theme_advanced_resize_horizontal' => false,
283                                         'dialog_type' => 'modal',
284                                         'formats' => "{
285                                                 alignleft : [
286                                                         {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}},
287                                                         {selector : 'img,table', classes : 'alignleft'}
288                                                 ],
289                                                 aligncenter : [
290                                                         {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}},
291                                                         {selector : 'img,table', classes : 'aligncenter'}
292                                                 ],
293                                                 alignright : [
294                                                         {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}},
295                                                         {selector : 'img,table', classes : 'alignright'}
296                                                 ],
297                                                 strikethrough : {inline : 'del'}
298                                         }",
299                                         'relative_urls' => false,
300                                         'remove_script_host' => false,
301                                         'convert_urls' => false,
302                                         'remove_linebreaks' => true,
303                                         'gecko_spellcheck' => true,
304                                         'keep_styles' => false,
305                                         'entities' => '38,amp,60,lt,62,gt',
306                                         'accessibility_focus' => true,
307                                         'tabfocus_elements' => 'major-publishing-actions',
308                                         'media_strict' => false,
309                                         'paste_remove_styles' => true,
310                                         'paste_remove_spans' => true,
311                                         'paste_strip_class_attributes' => 'all',
312                                         'paste_text_use_dialog' => true,
313                                         'extended_valid_elements' => 'article[*],aside[*],audio[*],canvas[*],command[*],datalist[*],details[*],embed[*],figcaption[*],figure[*],footer[*],header[*],hgroup[*],keygen[*],mark[*],meter[*],nav[*],output[*],progress[*],section[*],source[*],summary,time[*],video[*],wbr',
314                                         'wpeditimage_disable_captions' => $no_captions,
315                                         'wp_fullscreen_content_css' => self::$baseurl . '/plugins/wpfullscreen/css/wp-fullscreen.css',
316                                         'plugins' => implode( ',', $plugins )
317                                 );
318
319                                 // load editor_style.css if the current theme supports it
320                                 if ( ! empty( $editor_styles ) && is_array( $editor_styles ) ) {
321                                         $mce_css = array();
322                                         $editor_styles = array_unique($editor_styles);
323                                         $style_uri = get_stylesheet_directory_uri();
324                                         if ( ! is_child_theme() ) {
325                                                 foreach ( $editor_styles as $file )
326                                                         $mce_css[] = "$style_uri/$file";
327                                         } else {
328                                                 $style_dir    = get_stylesheet_directory();
329                                                 $template_uri = get_template_directory_uri();
330                                                 $template_dir = get_template_directory();
331
332                                                 foreach ( $editor_styles as $file ) {
333                                                         if ( file_exists( "$template_dir/$file" ) )
334                                                                 $mce_css[] = "$template_uri/$file";
335                                                 }
336
337                                                 foreach ( $editor_styles as $file ) {
338                                                         if ( file_exists( "$style_dir/$file" ) )
339                                                                 $mce_css[] = "$style_uri/$file";
340                                                 }
341                                         }
342                                         $mce_css = implode( ',', $mce_css );
343                                 } else {
344                                         $mce_css = '';
345                                 }
346
347                                 $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' );
348
349                                 if ( ! empty($mce_css) )
350                                         self::$first_init['content_css'] = $mce_css;
351                         }
352
353                         if ( $set['teeny'] ) {
354                                 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold', 'italic', 'underline', 'blockquote', 'separator', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'undo', 'redo', 'link', 'unlink', 'fullscreen'), $editor_id );
355                                 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = array();
356                         } else {
357                                 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ), $editor_id);
358                                 $mce_buttons_2 = apply_filters('mce_buttons_2', array( 'formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' ), $editor_id);
359                                 $mce_buttons_3 = apply_filters('mce_buttons_3', array(), $editor_id);
360                                 $mce_buttons_4 = apply_filters('mce_buttons_4', array(), $editor_id);
361                         }
362
363                         if ( $set['dfw'] ) {
364                                 // replace the first 'fullscreen' with 'wp_fullscreen'
365                                 if ( ($key = array_search('fullscreen', $mce_buttons)) !== false )
366                                         $mce_buttons[$key] = 'wp_fullscreen';
367                                 elseif ( ($key = array_search('fullscreen', $mce_buttons_2)) !== false )
368                                         $mce_buttons_2[$key] = 'wp_fullscreen';
369                                 elseif ( ($key = array_search('fullscreen', $mce_buttons_3)) !== false )
370                                         $mce_buttons_3[$key] = 'wp_fullscreen';
371                                 elseif ( ($key = array_search('fullscreen', $mce_buttons_4)) !== false )
372                                         $mce_buttons_4[$key] = 'wp_fullscreen';
373                         }
374
375                         $mceInit = array (
376                                 'elements' => $editor_id,
377                                 'wpautop' => (bool) $set['wpautop'],
378                                 'remove_linebreaks' => (bool) $set['wpautop'],
379                                 'apply_source_formatting' => (bool) !$set['wpautop'],
380                                 'theme_advanced_buttons1' => implode($mce_buttons, ','),
381                                 'theme_advanced_buttons2' => implode($mce_buttons_2, ','),
382                                 'theme_advanced_buttons3' => implode($mce_buttons_3, ','),
383                                 'theme_advanced_buttons4' => implode($mce_buttons_4, ',')
384                         );
385
386                         if ( $first_run )
387                                 $mceInit = array_merge(self::$first_init, $mceInit);
388
389                         if ( is_array($set['tinymce']) )
390                                 $mceInit = array_merge($mceInit, $set['tinymce']);
391
392                         // For people who really REALLY know what they're doing with TinyMCE
393                         // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
394                         // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through this filter.
395                         // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
396                         if ( $set['teeny'] ) {
397                                 $mceInit = apply_filters('teeny_mce_before_init', $mceInit, $editor_id);
398                         } else {
399                                 $mceInit = apply_filters('tiny_mce_before_init', $mceInit, $editor_id);
400                         }
401
402                         if ( empty($mceInit['theme_advanced_buttons3']) && !empty($mceInit['theme_advanced_buttons4']) ) {
403                                 $mceInit['theme_advanced_buttons3'] = $mceInit['theme_advanced_buttons4'];
404                                 $mceInit['theme_advanced_buttons4'] = '';
405                         }
406
407                         self::$mce_settings[$editor_id] = $mceInit;
408                 } // end if self::$this_tinymce
409         }
410
411         private static function _parse_init($init) {
412                 $options = '';
413
414                 foreach ( $init as $k => $v ) {
415                         if ( is_bool($v) ) {
416                                 $val = $v ? 'true' : 'false';
417                                 $options .= $k . ':' . $val . ',';
418                                 continue;
419                         } elseif ( !empty($v) && is_string($v) && ( ('{' == $v{0} && '}' == $v{strlen($v) - 1}) || ('[' == $v{0} && ']' == $v{strlen($v) - 1}) || preg_match('/^\(?function ?\(/', $v) ) ) {
420                                 $options .= $k . ':' . $v . ',';
421                                 continue;
422                         }
423                         $options .= $k . ':"' . $v . '",';
424                 }
425
426                 return '{' . trim( $options, ' ,' ) . '}';
427         }
428
429         public static function enqueue_scripts() {
430                 wp_enqueue_script('word-count');
431
432                 if ( self::$has_tinymce )
433                         wp_enqueue_script('editor');
434
435                 if ( self::$has_quicktags )
436                         wp_enqueue_script('quicktags');
437
438                 if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) ) {
439                         wp_enqueue_script('wplink');
440                         wp_enqueue_script('wpdialogs-popup');
441                         wp_enqueue_style('wp-jquery-ui-dialog');
442                 }
443
444                 if ( in_array('wpfullscreen', self::$plugins, true) || in_array('fullscreen', self::$qt_buttons, true) )
445                         wp_enqueue_script('wp-fullscreen');
446
447                 if ( self::$has_medialib ) {
448                         add_thickbox();
449                         wp_enqueue_script('media-upload');
450                 }
451         }
452
453         public static function editor_js() {
454                 global $tinymce_version, $concatenate_scripts, $compress_scripts;
455
456                 /**
457                  * Filter "tiny_mce_version" is deprecated
458                  *
459                  * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
460                  * These plugins can be refreshed by appending query string to the URL passed to "mce_external_plugins" filter.
461                  * If the plugin has a popup dialog, a query string can be added to the button action that opens it (in the plugin's code).
462                  */
463                 $version = 'ver=' . $tinymce_version;
464                 $tmce_on = !empty(self::$mce_settings);
465
466                 if ( ! isset($concatenate_scripts) )
467                         script_concat_settings();
468
469                 $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
470                         && false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
471
472                 if ( $tmce_on && 'en' != self::$mce_locale )
473                         include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
474
475                 $mceInit = $qtInit = '';
476                 if ( $tmce_on ) {
477                         foreach ( self::$mce_settings as $editor_id => $init ) {
478                                 $options = self::_parse_init( $init );
479                                 $mceInit .= "'$editor_id':{$options},";
480                         }
481                         $mceInit = '{' . trim($mceInit, ',') . '}';
482                 } else {
483                         $mceInit = '{}';
484                 }
485
486                 if ( !empty(self::$qt_settings) ) {
487                         foreach ( self::$qt_settings as $editor_id => $init ) {
488                                 $options = self::_parse_init( $init );
489                                 $qtInit .= "'$editor_id':{$options},";
490                         }
491                         $qtInit = '{' . trim($qtInit, ',') . '}';
492                 } else {
493                         $qtInit = '{}';
494                 }
495
496                 $ref = array(
497                         'plugins' => implode( ',', self::$plugins ),
498                         'theme' => 'advanced',
499                         'language' => self::$mce_locale
500                 );
501
502                 do_action('before_wp_tiny_mce', self::$mce_settings);
503 ?>
504
505         <script type="text/javascript">
506                 tinyMCEPreInit = {
507                         base : "<?php echo self::$baseurl; ?>",
508                         suffix : "",
509                         query : "<?php echo $version; ?>",
510                         mceInit : <?php echo $mceInit; ?>,
511                         qtInit : <?php echo $qtInit; ?>,
512                         ref : <?php echo self::_parse_init( $ref ); ?>,
513                         load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
514                 };
515         </script>
516 <?php
517
518                 $baseurl = self::$baseurl;
519
520                 if ( $tmce_on ) {
521                         if ( $compressed )
522                                 echo "<script type='text/javascript' src='{$baseurl}/wp-tinymce.php?c=1&amp;$version'></script>\n";
523                         else
524                                 echo "<script type='text/javascript' src='{$baseurl}/tiny_mce.js?$version'></script>\n";
525
526                         if ( 'en' != self::$mce_locale && isset($lang) )
527                                 echo "<script type='text/javascript'>\n$lang\n</script>\n";
528                         else
529                                 echo "<script type='text/javascript' src='{$baseurl}/langs/wp-langs-en.js?$version'></script>\n";
530                 }
531 ?>
532
533         <script type="text/javascript">
534                 (function(){
535                         var init, ed, qt, first_init, mce = <?php echo wp_default_editor() == 'tinymce' ? 'true' : 'false'; ?>;
536
537                         if ( typeof(tinymce) == 'object' ) {
538                                 // mark wp_theme/ui.css as loaded
539                                 tinymce.DOM.files[tinymce.baseURI.getURI() + '/themes/advanced/skins/wp_theme/ui.css'] = true;
540
541                                 for ( ed in tinyMCEPreInit.mceInit ) {
542                                         if ( first_init ) {
543                                                 init = tinyMCEPreInit.mceInit[ed] = tinymce.extend( {}, first_init, tinyMCEPreInit.mceInit[ed] );
544                                         } else {
545                                                 init = first_init = tinyMCEPreInit.mceInit[ed];
546                                         }
547
548                                         if ( mce )
549                                                 try { tinymce.init(init); } catch(e){}
550                                 }
551                         }
552
553                         if ( typeof(QTags) == 'function' ) {
554                                 for ( qt in tinyMCEPreInit.qtInit ) {
555                                         try { quicktags( tinyMCEPreInit.qtInit[qt] ); } catch(e){}
556                                 }
557                         }
558                 })();
559
560                 var wpActiveEditor;
561
562                 jQuery('.wp-editor-wrap').mousedown(function(e){
563                         wpActiveEditor = this.id.slice(3, -5);
564                 });
565
566 <?php
567
568                 if ( self::$ext_plugins )
569                         echo self::$ext_plugins . "\n";
570
571                 if ( ! $compressed && $tmce_on ) {
572 ?>
573                 (function(){var t=tinyMCEPreInit,sl=tinymce.ScriptLoader,ln=t.ref.language,th=t.ref.theme,pl=t.ref.plugins;sl.markDone(t.base+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'_dlg.js');sl.markDone(t.base+'/themes/advanced/skins/wp_theme/ui.css');tinymce.each(pl.split(','),function(n){if(n&&n.charAt(0)!='-'){sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'.js');sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'_dlg.js');}});})();
574 <?php
575                 }
576
577                 if ( !is_admin() )
578                         echo 'var ajaxurl = "' . admin_url('admin-ajax.php') . '";';
579 ?>
580         </script>
581 <?php
582
583                 if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) )
584                         self::wp_link_dialog();
585
586                 if ( in_array('wpfullscreen', self::$plugins, true) || in_array('fullscreen', self::$qt_buttons, true) )
587                         self::wp_fullscreen_html();
588
589                 do_action('after_wp_tiny_mce', self::$mce_settings);
590         }
591
592         public static function wp_fullscreen_html() {
593                 global $content_width, $post;
594
595                 $width = isset($content_width) && 800 > $content_width ? $content_width : 800;
596                 $width = $width + 22; // compensate for the padding and border
597                 $dfw_width = get_user_setting( 'dfw_width', $width );
598                 $save = isset($post->post_status) && $post->post_status == 'publish' ? __('Update') : __('Save');
599         ?>
600         <div id="wp-fullscreen-body">
601         <div id="fullscreen-topbar">
602                 <div id="wp-fullscreen-toolbar">
603                         <div id="wp-fullscreen-close"><a href="#" onclick="fullscreen.off();return false;"><?php _e('Exit fullscreen'); ?></a></div>
604                         <div id="wp-fullscreen-central-toolbar" style="width:<?php echo $width; ?>px;">
605
606                         <div id="wp-fullscreen-mode-bar"><div id="wp-fullscreen-modes">
607                                 <a href="#" onclick="fullscreen.switchmode('tinymce');return false;"><?php _e('Visual'); ?></a>
608                                 <a href="#" onclick="fullscreen.switchmode('html');return false;"><?php _e('HTML'); ?></a>
609                         </div></div>
610
611                         <div id="wp-fullscreen-button-bar"><div id="wp-fullscreen-buttons" class="wp_themeSkin">
612         <?php
613
614                 $buttons = array(
615                         // format: title, onclick, show in both editors
616                         'bold' => array( 'title' => __('Bold (Ctrl + B)'), 'onclick' => 'fullscreen.b();', 'both' => false ),
617                         'italic' => array( 'title' => __('Italic (Ctrl + I)'), 'onclick' => 'fullscreen.i();', 'both' => false ),
618                         '0' => 'separator',
619                         'bullist' => array( 'title' => __('Unordered list (Alt + Shift + U)'), 'onclick' => 'fullscreen.ul();', 'both' => false ),
620                         'numlist' => array( 'title' => __('Ordered list (Alt + Shift + O)'), 'onclick' => 'fullscreen.ol();', 'both' => false ),
621                         '1' => 'separator',
622                         'blockquote' => array( 'title' => __('Blockquote (Alt + Shift + Q)'), 'onclick' => 'fullscreen.blockquote();', 'both' => false ),
623                         'image' => array( 'title' => __('Insert/edit image (Alt + Shift + M)'), 'onclick' => "fullscreen.medialib();", 'both' => true ),
624                         '2' => 'separator',
625                         'link' => array( 'title' => __('Insert/edit link (Alt + Shift + A)'), 'onclick' => 'fullscreen.link();', 'both' => true ),
626                         'unlink' => array( 'title' => __('Unlink (Alt + Shift + S)'), 'onclick' => 'fullscreen.unlink();', 'both' => false ),
627                         '3' => 'separator',
628                         'help' => array( 'title' => __('Help (Alt + Shift + H)'), 'onclick' => 'fullscreen.help();', 'both' => false )
629                 );
630
631                 $buttons = apply_filters( 'wp_fullscreen_buttons', $buttons );
632
633                 foreach ( $buttons as $button => $args ) {
634                         if ( 'separator' == $args ) { ?>
635                                 <div><span aria-orientation="vertical" role="separator" class="mceSeparator"></span></div>
636         <?php           continue;
637                         } ?>
638
639                         <div<?php if ( $args['both'] ) { ?> class="wp-fullscreen-both"<?php } ?>>
640                         <a title="<?php echo $args['title']; ?>" onclick="<?php echo $args['onclick']; ?>return false;" class="mceButton mceButtonEnabled mce_<?php echo $button; ?>" href="#" id="wp_fs_<?php echo $button; ?>" role="button" aria-pressed="false">
641                         <span class="mceIcon mce_<?php echo $button; ?>"></span>
642                         </a>
643                         </div>
644         <?php
645                 } ?>
646
647                         </div></div>
648
649                         <div id="wp-fullscreen-save">
650                                 <span><?php if ( $post->post_status == 'publish' ) _e('Updated.'); else _e('Saved.'); ?></span>
651                                 <img src="images/wpspin_light.gif" alt="" />
652                                 <input type="button" class="button-primary" value="<?php echo $save; ?>" onclick="fullscreen.save();" />
653                         </div>
654
655                         </div>
656                 </div>
657         </div>
658
659         <div id="wp-fullscreen-wrap" style="width:<?php echo $dfw_width; ?>px;">
660                 <?php if ( post_type_supports($post->post_type, 'title') ) { ?>
661                 <label id="wp-fullscreen-title-prompt-text" for="wp-fullscreen-title"><?php echo apply_filters( 'enter_title_here', __( 'Enter title here' ), $post ); ?></label>
662                 <input type="text" id="wp-fullscreen-title" value="" autocomplete="off" />
663                 <?php } ?>
664
665                 <div id="wp-fullscreen-container">
666                         <textarea id="wp_mce_fullscreen"></textarea>
667                 </div>
668
669                 <div id="wp-fullscreen-status">
670                         <div id="wp-fullscreen-count"><?php printf( __( 'Word count: %s' ), '<span class="word-count">0</span>' ); ?></div>
671                         <div id="wp-fullscreen-tagline"><?php _e('Just write.'); ?></div>
672                 </div>
673         </div>
674         </div>
675
676         <div class="fullscreen-overlay" id="fullscreen-overlay"></div>
677         <div class="fullscreen-overlay fullscreen-fader fade-600" id="fullscreen-fader"></div>
678         <?php
679         }
680
681         /**
682          * Performs post queries for internal linking.
683          *
684          * @since 3.1.0
685          *
686          * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments.
687          * @return array Results.
688          */
689         public static function wp_link_query( $args = array() ) {
690                 $pts = get_post_types( array( 'public' => true ), 'objects' );
691                 $pt_names = array_keys( $pts );
692
693                 $query = array(
694                         'post_type' => $pt_names,
695                         'suppress_filters' => true,
696                         'update_post_term_cache' => false,
697                         'update_post_meta_cache' => false,
698                         'post_status' => 'publish',
699                         'order' => 'DESC',
700                         'orderby' => 'post_date',
701                         'posts_per_page' => 20,
702                 );
703
704                 $args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1;
705
706                 if ( isset( $args['s'] ) )
707                         $query['s'] = $args['s'];
708
709                 $query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0;
710
711                 // Do main query.
712                 $get_posts = new WP_Query;
713                 $posts = $get_posts->query( $query );
714                 // Check if any posts were found.
715                 if ( ! $get_posts->post_count )
716                         return false;
717
718                 // Build results.
719                 $results = array();
720                 foreach ( $posts as $post ) {
721                         if ( 'post' == $post->post_type )
722                                 $info = mysql2date( __( 'Y/m/d' ), $post->post_date );
723                         else
724                                 $info = $pts[ $post->post_type ]->labels->singular_name;
725
726                         $results[] = array(
727                                 'ID' => $post->ID,
728                                 'title' => trim( esc_html( strip_tags( get_the_title( $post ) ) ) ),
729                                 'permalink' => get_permalink( $post->ID ),
730                                 'info' => $info,
731                         );
732                 }
733
734                 return $results;
735         }
736
737         /**
738          * Dialog for internal linking.
739          *
740          * @since 3.1.0
741          */
742         public static function wp_link_dialog() {
743         ?>
744         <div style="display:none;">
745         <form id="wp-link" tabindex="-1">
746         <?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?>
747         <div id="link-selector">
748                 <div id="link-options">
749                         <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p>
750                         <div>
751                                 <label><span><?php _e( 'URL' ); ?></span><input id="url-field" type="text" tabindex="10" name="href" /></label>
752                         </div>
753                         <div>
754                                 <label><span><?php _e( 'Title' ); ?></span><input id="link-title-field" type="text" tabindex="20" name="linktitle" /></label>
755                         </div>
756                         <div class="link-target">
757                                 <label><input type="checkbox" id="link-target-checkbox" tabindex="30" /> <?php _e( 'Open link in a new window/tab' ); ?></label>
758                         </div>
759                 </div>
760                 <?php $show_internal = '1' == get_user_setting( 'wplink', '0' ); ?>
761                 <p class="howto toggle-arrow <?php if ( $show_internal ) echo 'toggle-arrow-active'; ?>" id="internal-toggle"><?php _e( 'Or link to existing content' ); ?></p>
762                 <div id="search-panel"<?php if ( ! $show_internal ) echo ' style="display:none"'; ?>>
763                         <div class="link-search-wrapper">
764                                 <label>
765                                         <span><?php _e( 'Search' ); ?></span>
766                                         <input type="text" id="search-field" class="link-search-field" tabindex="60" autocomplete="off" />
767                                         <img class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
768                                 </label>
769                         </div>
770                         <div id="search-results" class="query-results">
771                                 <ul></ul>
772                                 <div class="river-waiting">
773                                         <img class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
774                                 </div>
775                         </div>
776                         <div id="most-recent-results" class="query-results">
777                                 <div class="query-notice"><em><?php _e( 'No search term specified. Showing recent items.' ); ?></em></div>
778                                 <ul></ul>
779                                 <div class="river-waiting">
780                                         <img class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
781                                 </div>
782                         </div>
783                 </div>
784         </div>
785         <div class="submitbox">
786                 <div id="wp-link-cancel">
787                         <a class="submitdelete deletion" href="#"><?php _e( 'Cancel' ); ?></a>
788                 </div>
789                 <div id="wp-link-update">
790                         <input type="submit" tabindex="100" value="<?php esc_attr_e( 'Add Link' ); ?>" class="button-primary" id="wp-link-submit" name="wp-link-submit">
791                 </div>
792         </div>
793         </form>
794         </div>
795         <?php
796         }
797 }
798