PageRenderTime 194ms CodeModel.GetById 60ms app.highlight 77ms RepoModel.GetById 43ms app.codeStats 1ms

/wp-includes/class-wp-editor.php

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