wp/wp-includes/class-wp-editor.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    23 	private static $has_tinymce        = false;
    23 	private static $has_tinymce        = false;
    24 	private static $has_quicktags      = false;
    24 	private static $has_quicktags      = false;
    25 	private static $has_medialib       = false;
    25 	private static $has_medialib       = false;
    26 	private static $editor_buttons_css = true;
    26 	private static $editor_buttons_css = true;
    27 	private static $drag_drop_upload   = false;
    27 	private static $drag_drop_upload   = false;
    28 	private static $old_dfw_compat     = false;
       
    29 	private static $translation;
    28 	private static $translation;
    30 	private static $tinymce_scripts_printed = false;
    29 	private static $tinymce_scripts_printed = false;
    31 	private static $link_dialog_printed     = false;
    30 	private static $link_dialog_printed     = false;
    32 
    31 
    33 	private function __construct() {}
    32 	private function __construct() {}
    34 
    33 
    35 	/**
    34 	/**
    36 	 * Parse default arguments for the editor instance.
    35 	 * Parse default arguments for the editor instance.
    37 	 *
    36 	 *
    38 	 * @param string $editor_id ID for the current editor instance.
    37 	 * @since 3.3.0
       
    38 	 *
       
    39 	 * @param string $editor_id HTML ID for the textarea and TinyMCE and Quicktags instances.
       
    40 	 *                          Should not contain square brackets.
    39 	 * @param array  $settings {
    41 	 * @param array  $settings {
    40 	 *     Array of editor arguments.
    42 	 *     Array of editor arguments.
    41 	 *
    43 	 *
    42 	 *     @type bool       $wpautop           Whether to use wpautop(). Default true.
    44 	 *     @type bool       $wpautop           Whether to use wpautop(). Default true.
    43 	 *     @type bool       $media_buttons     Whether to show the Add Media/other media buttons.
    45 	 *     @type bool       $media_buttons     Whether to show the Add Media/other media buttons.
    54 	 *     @type string     $editor_css        Intended for extra styles for both Visual and Text editors.
    56 	 *     @type string     $editor_css        Intended for extra styles for both Visual and Text editors.
    55 	 *                                         Should include `<style>` tags, and can use "scoped". Default empty.
    57 	 *                                         Should include `<style>` tags, and can use "scoped". Default empty.
    56 	 *     @type string     $editor_class      Extra classes to add to the editor textarea element. Default empty.
    58 	 *     @type string     $editor_class      Extra classes to add to the editor textarea element. Default empty.
    57 	 *     @type bool       $teeny             Whether to output the minimal editor config. Examples include
    59 	 *     @type bool       $teeny             Whether to output the minimal editor config. Examples include
    58 	 *                                         Press This and the Comment editor. Default false.
    60 	 *                                         Press This and the Comment editor. Default false.
    59 	 *     @type bool       $dfw               Deprecated in 4.1. Since 4.3 used only to enqueue wp-fullscreen-stub.js
    61 	 *     @type bool       $dfw               Deprecated in 4.1. Unused.
    60 	 *                                         for backward compatibility.
       
    61 	 *     @type bool|array $tinymce           Whether to load TinyMCE. Can be used to pass settings directly to
    62 	 *     @type bool|array $tinymce           Whether to load TinyMCE. Can be used to pass settings directly to
    62 	 *                                         TinyMCE using an array. Default true.
    63 	 *                                         TinyMCE using an array. Default true.
    63 	 *     @type bool|array $quicktags         Whether to load Quicktags. Can be used to pass settings directly to
    64 	 *     @type bool|array $quicktags         Whether to load Quicktags. Can be used to pass settings directly to
    64 	 *                                         Quicktags using an array. Default true.
    65 	 *                                         Quicktags using an array. Default true.
    65 	 * }
    66 	 * }
    73 		 * @since 4.0.0
    74 		 * @since 4.0.0
    74 		 *
    75 		 *
    75 		 * @see _WP_Editors::parse_settings()
    76 		 * @see _WP_Editors::parse_settings()
    76 		 *
    77 		 *
    77 		 * @param array  $settings  Array of editor arguments.
    78 		 * @param array  $settings  Array of editor arguments.
    78 		 * @param string $editor_id ID for the current editor instance.
    79 		 * @param string $editor_id Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
    80 		 *                          when called from block editor's Classic block.
    79 		 */
    81 		 */
    80 		$settings = apply_filters( 'wp_editor_settings', $settings, $editor_id );
    82 		$settings = apply_filters( 'wp_editor_settings', $settings, $editor_id );
    81 
    83 
    82 		$set = wp_parse_args(
    84 		$set = wp_parse_args(
    83 			$settings,
    85 			$settings,
    92 				'tabindex'            => '',
    94 				'tabindex'            => '',
    93 				'tabfocus_elements'   => ':prev,:next',
    95 				'tabfocus_elements'   => ':prev,:next',
    94 				'editor_css'          => '',
    96 				'editor_css'          => '',
    95 				'editor_class'        => '',
    97 				'editor_class'        => '',
    96 				'teeny'               => false,
    98 				'teeny'               => false,
    97 				'dfw'                 => false,
       
    98 				'_content_editor_dfw' => false,
    99 				'_content_editor_dfw' => false,
    99 				'tinymce'             => true,
   100 				'tinymce'             => true,
   100 				'quicktags'           => true,
   101 				'quicktags'           => true,
   101 			)
   102 			)
   102 		);
   103 		);
   118 
   119 
   119 		if ( self::$this_quicktags ) {
   120 		if ( self::$this_quicktags ) {
   120 			self::$has_quicktags = true;
   121 			self::$has_quicktags = true;
   121 		}
   122 		}
   122 
   123 
   123 		if ( $set['dfw'] ) {
       
   124 			self::$old_dfw_compat = true;
       
   125 		}
       
   126 
       
   127 		if ( empty( $set['editor_height'] ) ) {
   124 		if ( empty( $set['editor_height'] ) ) {
   128 			return $set;
   125 			return $set;
   129 		}
   126 		}
   130 
   127 
   131 		if ( 'content' === $editor_id && empty( $set['tinymce']['wp_autoresize_on'] ) ) {
   128 		if ( 'content' === $editor_id && empty( $set['tinymce']['wp_autoresize_on'] ) ) {
   147 	}
   144 	}
   148 
   145 
   149 	/**
   146 	/**
   150 	 * Outputs the HTML for a single instance of the editor.
   147 	 * Outputs the HTML for a single instance of the editor.
   151 	 *
   148 	 *
   152 	 * @param string $content The initial content of the editor.
   149 	 * @since 3.3.0
   153 	 * @param string $editor_id ID for the textarea and TinyMCE and Quicktags instances (can contain only ASCII letters and numbers).
   150 	 *
   154 	 * @param array $settings See _WP_Editors::parse_settings() for description.
   151 	 * @param string $content   Initial content for the editor.
       
   152 	 * @param string $editor_id HTML ID for the textarea and TinyMCE and Quicktags instances.
       
   153 	 *                          Should not contain square brackets.
       
   154 	 * @param array  $settings  See _WP_Editors::parse_settings() for description.
   155 	 */
   155 	 */
   156 	public static function editor( $content, $editor_id, $settings = array() ) {
   156 	public static function editor( $content, $editor_id, $settings = array() ) {
   157 		$set            = self::parse_settings( $editor_id, $settings );
   157 		$set            = self::parse_settings( $editor_id, $settings );
   158 		$editor_class   = ' class="' . trim( esc_attr( $set['editor_class'] ) . ' wp-editor-area' ) . '"';
   158 		$editor_class   = ' class="' . trim( esc_attr( $set['editor_class'] ) . ' wp-editor-area' ) . '"';
   159 		$tabindex       = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
   159 		$tabindex       = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
   160 		$default_editor = 'html';
   160 		$default_editor = 'html';
   161 		$buttons        = $autocomplete = '';
   161 		$buttons        = '';
       
   162 		$autocomplete   = '';
   162 		$editor_id_attr = esc_attr( $editor_id );
   163 		$editor_id_attr = esc_attr( $editor_id );
   163 
   164 
   164 		if ( $set['drag_drop_upload'] ) {
   165 		if ( $set['drag_drop_upload'] ) {
   165 			self::$drag_drop_upload = true;
   166 			self::$drag_drop_upload = true;
   166 		}
   167 		}
   217 
   218 
   218 			if ( $set['media_buttons'] ) {
   219 			if ( $set['media_buttons'] ) {
   219 				self::$has_medialib = true;
   220 				self::$has_medialib = true;
   220 
   221 
   221 				if ( ! function_exists( 'media_buttons' ) ) {
   222 				if ( ! function_exists( 'media_buttons' ) ) {
   222 					include( ABSPATH . 'wp-admin/includes/media.php' );
   223 					require ABSPATH . 'wp-admin/includes/media.php';
   223 				}
   224 				}
   224 
   225 
   225 				echo '<div id="wp-' . $editor_id_attr . '-media-buttons" class="wp-media-buttons">';
   226 				echo '<div id="wp-' . $editor_id_attr . '-media-buttons" class="wp-media-buttons">';
   226 
   227 
   227 				/**
   228 				/**
   240 		}
   241 		}
   241 
   242 
   242 		$quicktags_toolbar = '';
   243 		$quicktags_toolbar = '';
   243 
   244 
   244 		if ( self::$this_quicktags ) {
   245 		if ( self::$this_quicktags ) {
   245 			if ( 'content' === $editor_id && ! empty( $GLOBALS['current_screen'] ) && $GLOBALS['current_screen']->base === 'post' ) {
   246 			if ( 'content' === $editor_id && ! empty( $GLOBALS['current_screen'] ) && 'post' === $GLOBALS['current_screen']->base ) {
   246 				$toolbar_id = 'ed_toolbar';
   247 				$toolbar_id = 'ed_toolbar';
   247 			} else {
   248 			} else {
   248 				$toolbar_id = 'qt_' . $editor_id_attr . '_toolbar';
   249 				$toolbar_id = 'qt_' . $editor_id_attr . '_toolbar';
   249 			}
   250 			}
   250 
   251 
   285 		// Remove the filter as the next editor on the same page may not need it.
   286 		// Remove the filter as the next editor on the same page may not need it.
   286 		if ( self::$this_tinymce ) {
   287 		if ( self::$this_tinymce ) {
   287 			remove_filter( 'the_editor_content', 'format_for_editor' );
   288 			remove_filter( 'the_editor_content', 'format_for_editor' );
   288 		}
   289 		}
   289 
   290 
   290 		// Back-compat for the `htmledit_pre` and `richedit_pre` filters
   291 		// Back-compat for the `htmledit_pre` and `richedit_pre` filters.
   291 		if ( 'html' === $default_editor && has_filter( 'htmledit_pre' ) ) {
   292 		if ( 'html' === $default_editor && has_filter( 'htmledit_pre' ) ) {
   292 			/** This filter is documented in wp-includes/deprecated.php */
   293 			/** This filter is documented in wp-includes/deprecated.php */
   293 			$content = apply_filters_deprecated( 'htmledit_pre', array( $content ), '4.3.0', 'format_for_editor' );
   294 			$content = apply_filters_deprecated( 'htmledit_pre', array( $content ), '4.3.0', 'format_for_editor' );
   294 		} elseif ( 'tinymce' === $default_editor && has_filter( 'richedit_pre' ) ) {
   295 		} elseif ( 'tinymce' === $default_editor && has_filter( 'richedit_pre' ) ) {
   295 			/** This filter is documented in wp-includes/deprecated.php */
   296 			/** This filter is documented in wp-includes/deprecated.php */
   305 
   306 
   306 		self::editor_settings( $editor_id, $set );
   307 		self::editor_settings( $editor_id, $set );
   307 	}
   308 	}
   308 
   309 
   309 	/**
   310 	/**
   310 	 * @global string $tinymce_version
   311 	 * @since 3.3.0
   311 	 *
   312 	 *
   312 	 * @param string $editor_id
   313 	 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   313 	 * @param array  $set
   314 	 * @param array  $set       Array of editor arguments.
   314 	 */
   315 	 */
   315 	public static function editor_settings( $editor_id, $set ) {
   316 	public static function editor_settings( $editor_id, $set ) {
   316 		global $tinymce_version;
       
   317 
       
   318 		if ( empty( self::$first_init ) ) {
   317 		if ( empty( self::$first_init ) ) {
   319 			if ( is_admin() ) {
   318 			if ( is_admin() ) {
   320 				add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_js' ), 50 );
   319 				add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_js' ), 50 );
   321 				add_action( 'admin_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 );
   320 				add_action( 'admin_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 );
   322 				add_action( 'admin_print_footer_scripts', array( __CLASS__, 'enqueue_scripts' ), 1 );
   321 				add_action( 'admin_print_footer_scripts', array( __CLASS__, 'enqueue_scripts' ), 1 );
   350 			 * Filters the Quicktags settings.
   349 			 * Filters the Quicktags settings.
   351 			 *
   350 			 *
   352 			 * @since 3.3.0
   351 			 * @since 3.3.0
   353 			 *
   352 			 *
   354 			 * @param array  $qtInit    Quicktags settings.
   353 			 * @param array  $qtInit    Quicktags settings.
   355 			 * @param string $editor_id The unique editor ID, e.g. 'content'.
   354 			 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   356 			 */
   355 			 */
   357 			$qtInit = apply_filters( 'quicktags_settings', $qtInit, $editor_id );
   356 			$qtInit = apply_filters( 'quicktags_settings', $qtInit, $editor_id );
   358 
   357 
   359 			self::$qt_settings[ $editor_id ] = $qtInit;
   358 			self::$qt_settings[ $editor_id ] = $qtInit;
   360 
   359 
   372 
   371 
   373 					/**
   372 					/**
   374 					 * Filters the list of teenyMCE plugins.
   373 					 * Filters the list of teenyMCE plugins.
   375 					 *
   374 					 *
   376 					 * @since 2.7.0
   375 					 * @since 2.7.0
       
   376 					 * @since 3.3.0 The `$editor_id` parameter was added.
   377 					 *
   377 					 *
   378 					 * @param array  $plugins   An array of teenyMCE plugins.
   378 					 * @param array  $plugins   An array of teenyMCE plugins.
   379 					 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   379 					 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   380 					 */
   380 					 */
   381 					$plugins = apply_filters( 'teeny_mce_plugins', array( 'colorpicker', 'lists', 'fullscreen', 'image', 'wordpress', 'wpeditimage', 'wplink' ), $editor_id );
   381 					$plugins = apply_filters(
       
   382 						'teeny_mce_plugins',
       
   383 						array(
       
   384 							'colorpicker',
       
   385 							'lists',
       
   386 							'fullscreen',
       
   387 							'image',
       
   388 							'wordpress',
       
   389 							'wpeditimage',
       
   390 							'wplink',
       
   391 						),
       
   392 						$editor_id
       
   393 					);
   382 				} else {
   394 				} else {
   383 
   395 
   384 					/**
   396 					/**
   385 					 * Filters the list of TinyMCE external plugins.
   397 					 * Filters the list of TinyMCE external plugins.
   386 					 *
   398 					 *
   393 					 *
   405 					 *
   394 					 * If the external plugin adds a button, it should be added with
   406 					 * If the external plugin adds a button, it should be added with
   395 					 * one of the 'mce_buttons' filters.
   407 					 * one of the 'mce_buttons' filters.
   396 					 *
   408 					 *
   397 					 * @since 2.5.0
   409 					 * @since 2.5.0
       
   410 					 * @since 5.3.0 The `$editor_id` parameter was added.
   398 					 *
   411 					 *
   399 					 * @param array $external_plugins An array of external TinyMCE plugins.
   412 					 * @param array  $external_plugins An array of external TinyMCE plugins.
       
   413 					 * @param string $editor_id        Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   414 					 *                                 when called from block editor's Classic block.
   400 					 */
   415 					 */
   401 					$mce_external_plugins = apply_filters( 'mce_external_plugins', array() );
   416 					$mce_external_plugins = apply_filters( 'mce_external_plugins', array(), $editor_id );
   402 
   417 
   403 					$plugins = array(
   418 					$plugins = array(
   404 						'charmap',
   419 						'charmap',
   405 						'colorpicker',
   420 						'colorpicker',
   406 						'hr',
   421 						'hr',
   430 					 *
   445 					 *
   431 					 * The filter specifies which of the default plugins included
   446 					 * The filter specifies which of the default plugins included
   432 					 * in WordPress should be added to the TinyMCE instance.
   447 					 * in WordPress should be added to the TinyMCE instance.
   433 					 *
   448 					 *
   434 					 * @since 3.3.0
   449 					 * @since 3.3.0
       
   450 					 * @since 5.3.0 The `$editor_id` parameter was added.
   435 					 *
   451 					 *
   436 					 * @param array $plugins An array of default TinyMCE plugins.
   452 					 * @param array  $plugins   An array of default TinyMCE plugins.
       
   453 					 * @param string $editor_id Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   454 					 *                          when called from block editor's Classic block.
   437 					 */
   455 					 */
   438 					$plugins = array_unique( apply_filters( 'tiny_mce_plugins', $plugins ) );
   456 					$plugins = array_unique( apply_filters( 'tiny_mce_plugins', $plugins, $editor_id ) );
   439 
   457 
   440 					if ( ( $key = array_search( 'spellchecker', $plugins ) ) !== false ) {
   458 					$key = array_search( 'spellchecker', $plugins, true );
       
   459 					if ( false !== $key ) {
   441 						// Remove 'spellchecker' from the internal plugins if added with 'tiny_mce_plugins' filter to prevent errors.
   460 						// Remove 'spellchecker' from the internal plugins if added with 'tiny_mce_plugins' filter to prevent errors.
   442 						// It can be added with 'mce_external_plugins'.
   461 						// It can be added with 'mce_external_plugins'.
   443 						unset( $plugins[ $key ] );
   462 						unset( $plugins[ $key ] );
   444 					}
   463 					}
   445 
   464 
   453 						 *
   472 						 *
   454 						 * The language file should follow the same format as wp_mce_translation(),
   473 						 * The language file should follow the same format as wp_mce_translation(),
   455 						 * and should define a variable ($strings) that holds all translated strings.
   474 						 * and should define a variable ($strings) that holds all translated strings.
   456 						 *
   475 						 *
   457 						 * @since 2.5.0
   476 						 * @since 2.5.0
       
   477 						 * @since 5.3.0 The `$editor_id` parameter was added.
   458 						 *
   478 						 *
   459 						 * @param array $translations Translations for external TinyMCE plugins.
   479 						 * @param array  $translations Translations for external TinyMCE plugins.
       
   480 						 * @param string $editor_id    Unique editor identifier, e.g. 'content'.
   460 						 */
   481 						 */
   461 						$mce_external_languages = apply_filters( 'mce_external_languages', array() );
   482 						$mce_external_languages = apply_filters( 'mce_external_languages', array(), $editor_id );
   462 
   483 
   463 						$loaded_langs = array();
   484 						$loaded_langs = array();
   464 						$strings      = '';
   485 						$strings      = '';
   465 
   486 
   466 						if ( ! empty( $mce_external_languages ) ) {
   487 						if ( ! empty( $mce_external_languages ) ) {
   467 							foreach ( $mce_external_languages as $name => $path ) {
   488 							foreach ( $mce_external_languages as $name => $path ) {
   468 								if ( @is_file( $path ) && @is_readable( $path ) ) {
   489 								if ( @is_file( $path ) && @is_readable( $path ) ) {
   469 									include_once( $path );
   490 									include_once $path;
   470 									$ext_plugins   .= $strings . "\n";
   491 									$ext_plugins   .= $strings . "\n";
   471 									$loaded_langs[] = $name;
   492 									$loaded_langs[] = $name;
   472 								}
   493 								}
   473 							}
   494 							}
   474 						}
   495 						}
   482 							$url                           = set_url_scheme( $url );
   503 							$url                           = set_url_scheme( $url );
   483 							$mce_external_plugins[ $name ] = $url;
   504 							$mce_external_plugins[ $name ] = $url;
   484 							$plugurl                       = dirname( $url );
   505 							$plugurl                       = dirname( $url );
   485 							$strings                       = '';
   506 							$strings                       = '';
   486 
   507 
   487 							// Try to load langs/[locale].js and langs/[locale]_dlg.js
   508 							// Try to load langs/[locale].js and langs/[locale]_dlg.js.
   488 							if ( ! in_array( $name, $loaded_langs, true ) ) {
   509 							if ( ! in_array( $name, $loaded_langs, true ) ) {
   489 								$path = str_replace( content_url(), '', $plugurl );
   510 								$path = str_replace( content_url(), '', $plugurl );
   490 								$path = WP_CONTENT_DIR . $path . '/langs/';
   511 								$path = WP_CONTENT_DIR . $path . '/langs/';
   491 
   512 
   492 								if ( function_exists( 'realpath' ) ) {
   513 								$path = trailingslashit( realpath( $path ) );
   493 									$path = trailingslashit( realpath( $path ) );
       
   494 								}
       
   495 
   514 
   496 								if ( @is_file( $path . $mce_locale . '.js' ) ) {
   515 								if ( @is_file( $path . $mce_locale . '.js' ) ) {
   497 									$strings .= @file_get_contents( $path . $mce_locale . '.js' ) . "\n";
   516 									$strings .= @file_get_contents( $path . $mce_locale . '.js' ) . "\n";
   498 								}
   517 								}
   499 
   518 
   500 								if ( @is_file( $path . $mce_locale . '_dlg.js' ) ) {
   519 								if ( @is_file( $path . $mce_locale . '_dlg.js' ) ) {
   501 									$strings .= @file_get_contents( $path . $mce_locale . '_dlg.js' ) . "\n";
   520 									$strings .= @file_get_contents( $path . $mce_locale . '_dlg.js' ) . "\n";
   502 								}
   521 								}
   503 
   522 
   504 								if ( 'en' != $mce_locale && empty( $strings ) ) {
   523 								if ( 'en' !== $mce_locale && empty( $strings ) ) {
   505 									if ( @is_file( $path . 'en.js' ) ) {
   524 									if ( @is_file( $path . 'en.js' ) ) {
   506 										$str1     = @file_get_contents( $path . 'en.js' );
   525 										$str1     = @file_get_contents( $path . 'en.js' );
   507 										$strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
   526 										$strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
   508 									}
   527 									}
   509 
   528 
   536 				/** This filter is documented in wp-admin/includes/media.php */
   555 				/** This filter is documented in wp-admin/includes/media.php */
   537 				if ( apply_filters( 'disable_captions', '' ) ) {
   556 				if ( apply_filters( 'disable_captions', '' ) ) {
   538 					$settings['wpeditimage_disable_captions'] = true;
   557 					$settings['wpeditimage_disable_captions'] = true;
   539 				}
   558 				}
   540 
   559 
   541 				$mce_css       = $settings['content_css'];
   560 				$mce_css = $settings['content_css'];
   542 				$editor_styles = get_editor_stylesheets();
   561 
   543 
   562 				/*
   544 				if ( ! empty( $editor_styles ) ) {
   563 				 * The `editor-style.css` added by the theme is generally intended for the editor instance on the Edit Post screen.
   545 					// Force urlencoding of commas.
   564 				 * Plugins that use wp_editor() on the front-end can decide whether to add the theme stylesheet
   546 					foreach ( $editor_styles as $key => $url ) {
   565 				 * by using `get_editor_stylesheets()` and the `mce_css` or `tiny_mce_before_init` filters, see below.
   547 						if ( strpos( $url, ',' ) !== false ) {
   566 				 */
   548 							$editor_styles[ $key ] = str_replace( ',', '%2C', $url );
   567 				if ( is_admin() ) {
       
   568 					$editor_styles = get_editor_stylesheets();
       
   569 
       
   570 					if ( ! empty( $editor_styles ) ) {
       
   571 						// Force urlencoding of commas.
       
   572 						foreach ( $editor_styles as $key => $url ) {
       
   573 							if ( strpos( $url, ',' ) !== false ) {
       
   574 								$editor_styles[ $key ] = str_replace( ',', '%2C', $url );
       
   575 							}
   549 						}
   576 						}
       
   577 
       
   578 						$mce_css .= ',' . implode( ',', $editor_styles );
   550 					}
   579 					}
   551 
       
   552 					$mce_css .= ',' . implode( ',', $editor_styles );
       
   553 				}
   580 				}
   554 
   581 
   555 				/**
   582 				/**
   556 				 * Filters the comma-delimited list of stylesheets to load in TinyMCE.
   583 				 * Filters the comma-delimited list of stylesheets to load in TinyMCE.
   557 				 *
   584 				 *
   569 
   596 
   570 				self::$first_init = $settings;
   597 				self::$first_init = $settings;
   571 			}
   598 			}
   572 
   599 
   573 			if ( $set['teeny'] ) {
   600 			if ( $set['teeny'] ) {
       
   601 				$mce_buttons = array(
       
   602 					'bold',
       
   603 					'italic',
       
   604 					'underline',
       
   605 					'blockquote',
       
   606 					'strikethrough',
       
   607 					'bullist',
       
   608 					'numlist',
       
   609 					'alignleft',
       
   610 					'aligncenter',
       
   611 					'alignright',
       
   612 					'undo',
       
   613 					'redo',
       
   614 					'link',
       
   615 					'fullscreen',
       
   616 				);
   574 
   617 
   575 				/**
   618 				/**
   576 				 * Filters the list of teenyMCE buttons (Text tab).
   619 				 * Filters the list of teenyMCE buttons (Text tab).
   577 				 *
   620 				 *
   578 				 * @since 2.7.0
   621 				 * @since 2.7.0
       
   622 				 * @since 3.3.0 The `$editor_id` parameter was added.
   579 				 *
   623 				 *
   580 				 * @param array  $buttons   An array of teenyMCE buttons.
   624 				 * @param array  $mce_buttons An array of teenyMCE buttons.
   581 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   625 				 * @param string $editor_id   Unique editor identifier, e.g. 'content'.
   582 				 */
   626 				 */
   583 				$mce_buttons   = apply_filters( 'teeny_mce_buttons', array( 'bold', 'italic', 'underline', 'blockquote', 'strikethrough', 'bullist', 'numlist', 'alignleft', 'aligncenter', 'alignright', 'undo', 'redo', 'link', 'fullscreen' ), $editor_id );
   627 				$mce_buttons   = apply_filters( 'teeny_mce_buttons', $mce_buttons, $editor_id );
   584 				$mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = array();
   628 				$mce_buttons_2 = array();
       
   629 				$mce_buttons_3 = array();
       
   630 				$mce_buttons_4 = array();
   585 			} else {
   631 			} else {
   586 				$mce_buttons = array( 'formatselect', 'bold', 'italic', 'bullist', 'numlist', 'blockquote', 'alignleft', 'aligncenter', 'alignright', 'link', 'wp_more', 'spellchecker' );
   632 				$mce_buttons = array(
       
   633 					'formatselect',
       
   634 					'bold',
       
   635 					'italic',
       
   636 					'bullist',
       
   637 					'numlist',
       
   638 					'blockquote',
       
   639 					'alignleft',
       
   640 					'aligncenter',
       
   641 					'alignright',
       
   642 					'link',
       
   643 					'wp_more',
       
   644 					'spellchecker',
       
   645 				);
   587 
   646 
   588 				if ( ! wp_is_mobile() ) {
   647 				if ( ! wp_is_mobile() ) {
   589 					if ( $set['_content_editor_dfw'] ) {
   648 					if ( $set['_content_editor_dfw'] ) {
   590 						$mce_buttons[] = 'wp_adv';
   649 						$mce_buttons[] = 'wp_adv';
   591 						$mce_buttons[] = 'dfw';
   650 						$mce_buttons[] = 'dfw';
   599 
   658 
   600 				/**
   659 				/**
   601 				 * Filters the first-row list of TinyMCE buttons (Visual tab).
   660 				 * Filters the first-row list of TinyMCE buttons (Visual tab).
   602 				 *
   661 				 *
   603 				 * @since 2.0.0
   662 				 * @since 2.0.0
       
   663 				 * @since 3.3.0 The `$editor_id` parameter was added.
   604 				 *
   664 				 *
   605 				 * @param array  $buttons   First-row list of buttons.
   665 				 * @param array  $mce_buttons First-row list of buttons.
   606 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   666 				 * @param string $editor_id   Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   667 				 *                            when called from block editor's Classic block.
   607 				 */
   668 				 */
   608 				$mce_buttons = apply_filters( 'mce_buttons', $mce_buttons, $editor_id );
   669 				$mce_buttons = apply_filters( 'mce_buttons', $mce_buttons, $editor_id );
   609 
   670 
   610 				$mce_buttons_2 = array( 'strikethrough', 'hr', 'forecolor', 'pastetext', 'removeformat', 'charmap', 'outdent', 'indent', 'undo', 'redo' );
   671 				$mce_buttons_2 = array(
       
   672 					'strikethrough',
       
   673 					'hr',
       
   674 					'forecolor',
       
   675 					'pastetext',
       
   676 					'removeformat',
       
   677 					'charmap',
       
   678 					'outdent',
       
   679 					'indent',
       
   680 					'undo',
       
   681 					'redo',
       
   682 				);
   611 
   683 
   612 				if ( ! wp_is_mobile() ) {
   684 				if ( ! wp_is_mobile() ) {
   613 					$mce_buttons_2[] = 'wp_help';
   685 					$mce_buttons_2[] = 'wp_help';
   614 				}
   686 				}
   615 
   687 
   616 				/**
   688 				/**
   617 				 * Filters the second-row list of TinyMCE buttons (Visual tab).
   689 				 * Filters the second-row list of TinyMCE buttons (Visual tab).
   618 				 *
   690 				 *
   619 				 * @since 2.0.0
   691 				 * @since 2.0.0
       
   692 				 * @since 3.3.0 The `$editor_id` parameter was added.
   620 				 *
   693 				 *
   621 				 * @param array  $buttons   Second-row list of buttons.
   694 				 * @param array  $mce_buttons_2 Second-row list of buttons.
   622 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   695 				 * @param string $editor_id     Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   696 				 *                              when called from block editor's Classic block.
   623 				 */
   697 				 */
   624 				$mce_buttons_2 = apply_filters( 'mce_buttons_2', $mce_buttons_2, $editor_id );
   698 				$mce_buttons_2 = apply_filters( 'mce_buttons_2', $mce_buttons_2, $editor_id );
   625 
   699 
   626 				/**
   700 				/**
   627 				 * Filters the third-row list of TinyMCE buttons (Visual tab).
   701 				 * Filters the third-row list of TinyMCE buttons (Visual tab).
   628 				 *
   702 				 *
   629 				 * @since 2.0.0
   703 				 * @since 2.0.0
       
   704 				 * @since 3.3.0 The `$editor_id` parameter was added.
   630 				 *
   705 				 *
   631 				 * @param array  $buttons   Third-row list of buttons.
   706 				 * @param array  $mce_buttons_3 Third-row list of buttons.
   632 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   707 				 * @param string $editor_id     Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   708 				 *                              when called from block editor's Classic block.
   633 				 */
   709 				 */
   634 				$mce_buttons_3 = apply_filters( 'mce_buttons_3', array(), $editor_id );
   710 				$mce_buttons_3 = apply_filters( 'mce_buttons_3', array(), $editor_id );
   635 
   711 
   636 				/**
   712 				/**
   637 				 * Filters the fourth-row list of TinyMCE buttons (Visual tab).
   713 				 * Filters the fourth-row list of TinyMCE buttons (Visual tab).
   638 				 *
   714 				 *
   639 				 * @since 2.5.0
   715 				 * @since 2.5.0
       
   716 				 * @since 3.3.0 The `$editor_id` parameter was added.
   640 				 *
   717 				 *
   641 				 * @param array  $buttons   Fourth-row list of buttons.
   718 				 * @param array  $mce_buttons_4 Fourth-row list of buttons.
   642 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   719 				 * @param string $editor_id     Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   720 				 *                              when called from block editor's Classic block.
   643 				 */
   721 				 */
   644 				$mce_buttons_4 = apply_filters( 'mce_buttons_4', array(), $editor_id );
   722 				$mce_buttons_4 = apply_filters( 'mce_buttons_4', array(), $editor_id );
   645 			}
   723 			}
   646 
   724 
   647 			$body_class = $editor_id;
   725 			$body_class = $editor_id;
   648 
   726 
   649 			if ( $post = get_post() ) {
   727 			$post = get_post();
       
   728 			if ( $post ) {
   650 				$body_class .= ' post-type-' . sanitize_html_class( $post->post_type ) . ' post-status-' . sanitize_html_class( $post->post_status );
   729 				$body_class .= ' post-type-' . sanitize_html_class( $post->post_type ) . ' post-status-' . sanitize_html_class( $post->post_status );
   651 
   730 
   652 				if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
   731 				if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
   653 					$post_format = get_post_format( $post );
   732 					$post_format = get_post_format( $post );
   654 					if ( $post_format && ! is_wp_error( $post_format ) ) {
   733 					if ( $post_format && ! is_wp_error( $post_format ) ) {
   658 					}
   737 					}
   659 				}
   738 				}
   660 
   739 
   661 				$page_template = get_page_template_slug( $post );
   740 				$page_template = get_page_template_slug( $post );
   662 
   741 
   663 				if ( $page_template !== false ) {
   742 				if ( false !== $page_template ) {
   664 					$page_template = empty( $page_template ) ? 'default' : str_replace( '.', '-', basename( $page_template, '.php' ) );
   743 					$page_template = empty( $page_template ) ? 'default' : str_replace( '.', '-', basename( $page_template, '.php' ) );
   665 					$body_class   .= ' page-template-' . sanitize_html_class( $page_template );
   744 					$body_class   .= ' page-template-' . sanitize_html_class( $page_template );
   666 				}
   745 				}
   667 			}
   746 			}
   668 
   747 
   683 				'toolbar4'          => implode( ',', $mce_buttons_4 ),
   762 				'toolbar4'          => implode( ',', $mce_buttons_4 ),
   684 				'tabfocus_elements' => $set['tabfocus_elements'],
   763 				'tabfocus_elements' => $set['tabfocus_elements'],
   685 				'body_class'        => $body_class,
   764 				'body_class'        => $body_class,
   686 			);
   765 			);
   687 
   766 
   688 			// Merge with the first part of the init array
   767 			// Merge with the first part of the init array.
   689 			$mceInit = array_merge( self::$first_init, $mceInit );
   768 			$mceInit = array_merge( self::$first_init, $mceInit );
   690 
   769 
   691 			if ( is_array( $set['tinymce'] ) ) {
   770 			if ( is_array( $set['tinymce'] ) ) {
   692 				$mceInit = array_merge( $mceInit, $set['tinymce'] );
   771 				$mceInit = array_merge( $mceInit, $set['tinymce'] );
   693 			}
   772 			}
   704 
   783 
   705 				/**
   784 				/**
   706 				 * Filters the teenyMCE config before init.
   785 				 * Filters the teenyMCE config before init.
   707 				 *
   786 				 *
   708 				 * @since 2.7.0
   787 				 * @since 2.7.0
       
   788 				 * @since 3.3.0 The `$editor_id` parameter was added.
   709 				 *
   789 				 *
   710 				 * @param array  $mceInit   An array with teenyMCE config.
   790 				 * @param array  $mceInit   An array with teenyMCE config.
   711 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   791 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   712 				 */
   792 				 */
   713 				$mceInit = apply_filters( 'teeny_mce_before_init', $mceInit, $editor_id );
   793 				$mceInit = apply_filters( 'teeny_mce_before_init', $mceInit, $editor_id );
   715 
   795 
   716 				/**
   796 				/**
   717 				 * Filters the TinyMCE config before init.
   797 				 * Filters the TinyMCE config before init.
   718 				 *
   798 				 *
   719 				 * @since 2.5.0
   799 				 * @since 2.5.0
       
   800 				 * @since 3.3.0 The `$editor_id` parameter was added.
   720 				 *
   801 				 *
   721 				 * @param array  $mceInit   An array with TinyMCE config.
   802 				 * @param array  $mceInit   An array with TinyMCE config.
   722 				 * @param string $editor_id Unique editor identifier, e.g. 'content'.
   803 				 * @param string $editor_id Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
       
   804 				 *                          when called from block editor's Classic block.
   723 				 */
   805 				 */
   724 				$mceInit = apply_filters( 'tiny_mce_before_init', $mceInit, $editor_id );
   806 				$mceInit = apply_filters( 'tiny_mce_before_init', $mceInit, $editor_id );
   725 			}
   807 			}
   726 
   808 
   727 			if ( empty( $mceInit['toolbar3'] ) && ! empty( $mceInit['toolbar4'] ) ) {
   809 			if ( empty( $mceInit['toolbar3'] ) && ! empty( $mceInit['toolbar4'] ) ) {
   728 				$mceInit['toolbar3'] = $mceInit['toolbar4'];
   810 				$mceInit['toolbar3'] = $mceInit['toolbar4'];
   729 				$mceInit['toolbar4'] = '';
   811 				$mceInit['toolbar4'] = '';
   730 			}
   812 			}
   731 
   813 
   732 			self::$mce_settings[ $editor_id ] = $mceInit;
   814 			self::$mce_settings[ $editor_id ] = $mceInit;
   733 		} // end if self::$this_tinymce
   815 		} // End if self::$this_tinymce.
   734 	}
   816 	}
   735 
   817 
   736 	/**
   818 	/**
       
   819 	 * @since 3.3.0
       
   820 	 *
   737 	 * @param array $init
   821 	 * @param array $init
   738 	 * @return string
   822 	 * @return string
   739 	 */
   823 	 */
   740 	private static function _parse_init( $init ) {
   824 	private static function _parse_init( $init ) {
   741 		$options = '';
   825 		$options = '';
   744 			if ( is_bool( $value ) ) {
   828 			if ( is_bool( $value ) ) {
   745 				$val      = $value ? 'true' : 'false';
   829 				$val      = $value ? 'true' : 'false';
   746 				$options .= $key . ':' . $val . ',';
   830 				$options .= $key . ':' . $val . ',';
   747 				continue;
   831 				continue;
   748 			} elseif ( ! empty( $value ) && is_string( $value ) && (
   832 			} elseif ( ! empty( $value ) && is_string( $value ) && (
   749 				( '{' == $value{0} && '}' == $value{strlen( $value ) - 1} ) ||
   833 				( '{' === $value[0] && '}' === $value[ strlen( $value ) - 1 ] ) ||
   750 				( '[' == $value{0} && ']' == $value{strlen( $value ) - 1} ) ||
   834 				( '[' === $value[0] && ']' === $value[ strlen( $value ) - 1 ] ) ||
   751 				preg_match( '/^\(?function ?\(/', $value ) ) ) {
   835 				preg_match( '/^\(?function ?\(/', $value ) ) ) {
   752 
   836 
   753 				$options .= $key . ':' . $value . ',';
   837 				$options .= $key . ':' . $value . ',';
   754 				continue;
   838 				continue;
   755 			}
   839 			}
   758 
   842 
   759 		return '{' . trim( $options, ' ,' ) . '}';
   843 		return '{' . trim( $options, ' ,' ) . '}';
   760 	}
   844 	}
   761 
   845 
   762 	/**
   846 	/**
   763 	 *
   847 	 * @since 3.3.0
   764 	 * @static
       
   765 	 *
   848 	 *
   766 	 * @param bool $default_scripts Optional. Whether default scripts should be enqueued. Default false.
   849 	 * @param bool $default_scripts Optional. Whether default scripts should be enqueued. Default false.
   767 	 */
   850 	 */
   768 	public static function enqueue_scripts( $default_scripts = false ) {
   851 	public static function enqueue_scripts( $default_scripts = false ) {
   769 		if ( $default_scripts || self::$has_tinymce ) {
   852 		if ( $default_scripts || self::$has_tinymce ) {
   776 		}
   859 		}
   777 
   860 
   778 		if ( $default_scripts || in_array( 'wplink', self::$plugins, true ) || in_array( 'link', self::$qt_buttons, true ) ) {
   861 		if ( $default_scripts || in_array( 'wplink', self::$plugins, true ) || in_array( 'link', self::$qt_buttons, true ) ) {
   779 			wp_enqueue_script( 'wplink' );
   862 			wp_enqueue_script( 'wplink' );
   780 			wp_enqueue_script( 'jquery-ui-autocomplete' );
   863 			wp_enqueue_script( 'jquery-ui-autocomplete' );
   781 		}
       
   782 
       
   783 		if ( self::$old_dfw_compat ) {
       
   784 			wp_enqueue_script( 'wp-fullscreen-stub' );
       
   785 		}
   864 		}
   786 
   865 
   787 		if ( self::$has_medialib ) {
   866 		if ( self::$has_medialib ) {
   788 			add_thickbox();
   867 			add_thickbox();
   789 			wp_enqueue_script( 'media-upload' );
   868 			wp_enqueue_script( 'media-upload' );
   821 			return;
   900 			return;
   822 		}
   901 		}
   823 
   902 
   824 		self::enqueue_scripts( true );
   903 		self::enqueue_scripts( true );
   825 
   904 
   826 		// Also add wp-includes/css/editor.css
   905 		// Also add wp-includes/css/editor.css.
   827 		wp_enqueue_style( 'editor-buttons' );
   906 		wp_enqueue_style( 'editor-buttons' );
   828 
   907 
   829 		if ( is_admin() ) {
   908 		if ( is_admin() ) {
   830 			add_action( 'admin_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 );
   909 			add_action( 'admin_print_footer_scripts', array( __CLASS__, 'force_uncompressed_tinymce' ), 1 );
   831 			add_action( 'admin_print_footer_scripts', array( __CLASS__, 'print_default_editor_scripts' ), 45 );
   910 			add_action( 'admin_print_footer_scripts', array( __CLASS__, 'print_default_editor_scripts' ), 45 );
   854 
   933 
   855 			if ( is_rtl() ) {
   934 			if ( is_rtl() ) {
   856 				$settings['directionality'] = 'rtl';
   935 				$settings['directionality'] = 'rtl';
   857 			}
   936 			}
   858 
   937 
   859 			// In production all plugins are loaded (they are in wp-editor.js.gz).
   938 			/*
   860 			// The 'wpview', 'wpdialogs', and 'media' TinyMCE plugins are not initialized by default.
   939 			 * In production all plugins are loaded (they are in wp-editor.js.gz).
   861 			// Can be added from js by using the 'wp-before-tinymce-init' event.
   940 			 * The 'wpview', 'wpdialogs', and 'media' TinyMCE plugins are not initialized by default.
       
   941 			 * Can be added from js by using the 'wp-before-tinymce-init' event.
       
   942 			 */
   862 			$settings['plugins'] = implode(
   943 			$settings['plugins'] = implode(
   863 				',',
   944 				',',
   864 				array(
   945 				array(
   865 					'charmap',
   946 					'charmap',
   866 					'colorpicker',
   947 					'colorpicker',
   931 		do_action( 'print_default_editor_scripts' );
  1012 		do_action( 'print_default_editor_scripts' );
   932 
  1013 
   933 		self::wp_link_dialog();
  1014 		self::wp_link_dialog();
   934 	}
  1015 	}
   935 
  1016 
       
  1017 	/**
       
  1018 	 * Returns the TinyMCE locale.
       
  1019 	 *
       
  1020 	 * @since 4.8.0
       
  1021 	 *
       
  1022 	 * @return string
       
  1023 	 */
   936 	public static function get_mce_locale() {
  1024 	public static function get_mce_locale() {
   937 		if ( empty( self::$mce_locale ) ) {
  1025 		if ( empty( self::$mce_locale ) ) {
   938 			$mce_locale       = get_user_locale();
  1026 			$mce_locale       = get_user_locale();
   939 			self::$mce_locale = empty( $mce_locale ) ? 'en' : strtolower( substr( $mce_locale, 0, 2 ) ); // ISO 639-1
  1027 			self::$mce_locale = empty( $mce_locale ) ? 'en' : strtolower( substr( $mce_locale, 0, 2 ) ); // ISO 639-1.
   940 		}
  1028 		}
   941 
  1029 
   942 		return self::$mce_locale;
  1030 		return self::$mce_locale;
   943 	}
  1031 	}
   944 
  1032 
       
  1033 	/**
       
  1034 	 * Returns the TinyMCE base URL.
       
  1035 	 *
       
  1036 	 * @since 4.8.0
       
  1037 	 *
       
  1038 	 * @return string
       
  1039 	 */
   945 	public static function get_baseurl() {
  1040 	public static function get_baseurl() {
   946 		if ( empty( self::$baseurl ) ) {
  1041 		if ( empty( self::$baseurl ) ) {
   947 			self::$baseurl = includes_url( 'js/tinymce' );
  1042 			self::$baseurl = includes_url( 'js/tinymce' );
   948 		}
  1043 		}
   949 
  1044 
   951 	}
  1046 	}
   952 
  1047 
   953 	/**
  1048 	/**
   954 	 * Returns the default TinyMCE settings.
  1049 	 * Returns the default TinyMCE settings.
   955 	 * Doesn't include plugins, buttons, editor selector.
  1050 	 * Doesn't include plugins, buttons, editor selector.
       
  1051 	 *
       
  1052 	 * @since 4.8.0
   956 	 *
  1053 	 *
   957 	 * @global string $tinymce_version
  1054 	 * @global string $tinymce_version
   958 	 *
  1055 	 *
   959 	 * @return array
  1056 	 * @return array
   960 	 */
  1057 	 */
   999 			'cache_suffix'                 => 'wp-mce-' . $tinymce_version,
  1096 			'cache_suffix'                 => 'wp-mce-' . $tinymce_version,
  1000 			'resize'                       => 'vertical',
  1097 			'resize'                       => 'vertical',
  1001 			'menubar'                      => false,
  1098 			'menubar'                      => false,
  1002 			'branding'                     => false,
  1099 			'branding'                     => false,
  1003 
  1100 
  1004 			// Limit the preview styles in the menu/toolbar
  1101 			// Limit the preview styles in the menu/toolbar.
  1005 			'preview_styles'               => 'font-family font-size font-weight font-style text-decoration text-transform',
  1102 			'preview_styles'               => 'font-family font-size font-weight font-style text-decoration text-transform',
  1006 
  1103 
  1007 			'end_container_on_empty_block' => true,
  1104 			'end_container_on_empty_block' => true,
  1008 			'wpeditimage_html5_captions'   => true,
  1105 			'wpeditimage_html5_captions'   => true,
  1009 			'wp_lang_attr'                 => get_bloginfo( 'language' ),
  1106 			'wp_lang_attr'                 => get_bloginfo( 'language' ),
  1012 		);
  1109 		);
  1013 
  1110 
  1014 		$suffix  = SCRIPT_DEBUG ? '' : '.min';
  1111 		$suffix  = SCRIPT_DEBUG ? '' : '.min';
  1015 		$version = 'ver=' . get_bloginfo( 'version' );
  1112 		$version = 'ver=' . get_bloginfo( 'version' );
  1016 
  1113 
  1017 		// Default stylesheets
  1114 		// Default stylesheets.
  1018 		$settings['content_css'] = includes_url( "css/dashicons$suffix.css?$version" ) . ',' .
  1115 		$settings['content_css'] = includes_url( "css/dashicons$suffix.css?$version" ) . ',' .
  1019 			includes_url( "js/tinymce/skins/wordpress/wp-content.css?$version" );
  1116 			includes_url( "js/tinymce/skins/wordpress/wp-content.css?$version" );
  1020 
  1117 
  1021 		return $settings;
  1118 		return $settings;
  1022 	}
  1119 	}
  1023 
  1120 
       
  1121 	/**
       
  1122 	 * @since 4.7.0
       
  1123 	 *
       
  1124 	 * @return array
       
  1125 	 */
  1024 	private static function get_translation() {
  1126 	private static function get_translation() {
  1025 		if ( empty( self::$translation ) ) {
  1127 		if ( empty( self::$translation ) ) {
  1026 			self::$translation = array(
  1128 			self::$translation = array(
  1027 				// Default TinyMCE strings
  1129 				// Default TinyMCE strings.
  1028 				'New document'                         => __( 'New document' ),
  1130 				'New document'                         => __( 'New document' ),
  1029 				'Formats'                              => _x( 'Formats', 'TinyMCE' ),
  1131 				'Formats'                              => _x( 'Formats', 'TinyMCE' ),
  1030 
  1132 
  1031 				'Headings'                             => _x( 'Headings', 'TinyMCE' ),
  1133 				'Headings'                             => _x( 'Headings', 'TinyMCE' ),
  1032 				'Heading 1'                            => array( __( 'Heading 1' ), 'access1' ),
  1134 				'Heading 1'                            => array( __( 'Heading 1' ), 'access1' ),
  1034 				'Heading 3'                            => array( __( 'Heading 3' ), 'access3' ),
  1136 				'Heading 3'                            => array( __( 'Heading 3' ), 'access3' ),
  1035 				'Heading 4'                            => array( __( 'Heading 4' ), 'access4' ),
  1137 				'Heading 4'                            => array( __( 'Heading 4' ), 'access4' ),
  1036 				'Heading 5'                            => array( __( 'Heading 5' ), 'access5' ),
  1138 				'Heading 5'                            => array( __( 'Heading 5' ), 'access5' ),
  1037 				'Heading 6'                            => array( __( 'Heading 6' ), 'access6' ),
  1139 				'Heading 6'                            => array( __( 'Heading 6' ), 'access6' ),
  1038 
  1140 
  1039 				/* translators: block tags */
  1141 				/* translators: Block tags. */
  1040 				'Blocks'                               => _x( 'Blocks', 'TinyMCE' ),
  1142 				'Blocks'                               => _x( 'Blocks', 'TinyMCE' ),
  1041 				'Paragraph'                            => array( __( 'Paragraph' ), 'access7' ),
  1143 				'Paragraph'                            => array( __( 'Paragraph' ), 'access7' ),
  1042 				'Blockquote'                           => array( __( 'Blockquote' ), 'accessQ' ),
  1144 				'Blockquote'                           => array( __( 'Blockquote' ), 'accessQ' ),
  1043 				'Div'                                  => _x( 'Div', 'HTML tag' ),
  1145 				'Div'                                  => _x( 'Div', 'HTML tag' ),
  1044 				'Pre'                                  => _x( 'Pre', 'HTML tag' ),
  1146 				'Pre'                                  => _x( 'Pre', 'HTML tag' ),
  1087 				'Lower Alpha'                          => _x( 'Lower Alpha', 'list style' ),
  1189 				'Lower Alpha'                          => _x( 'Lower Alpha', 'list style' ),
  1088 				'Upper Alpha'                          => _x( 'Upper Alpha', 'list style' ),
  1190 				'Upper Alpha'                          => _x( 'Upper Alpha', 'list style' ),
  1089 				'Upper Roman'                          => _x( 'Upper Roman', 'list style' ),
  1191 				'Upper Roman'                          => _x( 'Upper Roman', 'list style' ),
  1090 				'Lower Roman'                          => _x( 'Lower Roman', 'list style' ),
  1192 				'Lower Roman'                          => _x( 'Lower Roman', 'list style' ),
  1091 
  1193 
  1092 				// Anchor plugin
  1194 				// Anchor plugin.
  1093 				'Name'                                 => _x( 'Name', 'Name of link anchor (TinyMCE)' ),
  1195 				'Name'                                 => _x( 'Name', 'Name of link anchor (TinyMCE)' ),
  1094 				'Anchor'                               => _x( 'Anchor', 'Link anchor (TinyMCE)' ),
  1196 				'Anchor'                               => _x( 'Anchor', 'Link anchor (TinyMCE)' ),
  1095 				'Anchors'                              => _x( 'Anchors', 'Link anchors (TinyMCE)' ),
  1197 				'Anchors'                              => _x( 'Anchors', 'Link anchors (TinyMCE)' ),
  1096 				'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.' =>
  1198 				'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.' =>
  1097 					__( 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.' ),
  1199 					__( 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.' ),
  1098 				'Id'                                   => _x( 'Id', 'Id for link anchor (TinyMCE)' ),
  1200 				'Id'                                   => _x( 'Id', 'Id for link anchor (TinyMCE)' ),
  1099 
  1201 
  1100 				// Fullpage plugin
  1202 				// Fullpage plugin.
  1101 				'Document properties'                  => __( 'Document properties' ),
  1203 				'Document properties'                  => __( 'Document properties' ),
  1102 				'Robots'                               => __( 'Robots' ),
  1204 				'Robots'                               => __( 'Robots' ),
  1103 				'Title'                                => __( 'Title' ),
  1205 				'Title'                                => __( 'Title' ),
  1104 				'Keywords'                             => __( 'Keywords' ),
  1206 				'Keywords'                             => __( 'Keywords' ),
  1105 				'Encoding'                             => __( 'Encoding' ),
  1207 				'Encoding'                             => __( 'Encoding' ),
  1106 				'Description'                          => __( 'Description' ),
  1208 				'Description'                          => __( 'Description' ),
  1107 				'Author'                               => __( 'Author' ),
  1209 				'Author'                               => __( 'Author' ),
  1108 
  1210 
  1109 				// Media, image plugins
  1211 				// Media, image plugins.
  1110 				'Image'                                => __( 'Image' ),
  1212 				'Image'                                => __( 'Image' ),
  1111 				'Insert/edit image'                    => array( __( 'Insert/edit image' ), 'accessM' ),
  1213 				'Insert/edit image'                    => array( __( 'Insert/edit image' ), 'accessM' ),
  1112 				'General'                              => __( 'General' ),
  1214 				'General'                              => __( 'General' ),
  1113 				'Advanced'                             => __( 'Advanced' ),
  1215 				'Advanced'                             => __( 'Advanced' ),
  1114 				'Source'                               => __( 'Source' ),
  1216 				'Source'                               => __( 'Source' ),
  1130 				'Alternative source'                   => __( 'Alternative source' ),
  1232 				'Alternative source'                   => __( 'Alternative source' ),
  1131 				'Paste your embed code below:'         => __( 'Paste your embed code below:' ),
  1233 				'Paste your embed code below:'         => __( 'Paste your embed code below:' ),
  1132 				'Insert video'                         => __( 'Insert video' ),
  1234 				'Insert video'                         => __( 'Insert video' ),
  1133 				'Embed'                                => __( 'Embed' ),
  1235 				'Embed'                                => __( 'Embed' ),
  1134 
  1236 
  1135 				// Each of these have a corresponding plugin
  1237 				// Each of these have a corresponding plugin.
  1136 				'Special character'                    => __( 'Special character' ),
  1238 				'Special character'                    => __( 'Special character' ),
  1137 				'Right to left'                        => _x( 'Right to left', 'editor button' ),
  1239 				'Right to left'                        => _x( 'Right to left', 'editor button' ),
  1138 				'Left to right'                        => _x( 'Left to right', 'editor button' ),
  1240 				'Left to right'                        => _x( 'Left to right', 'editor button' ),
  1139 				'Emoticons'                            => __( 'Emoticons' ),
  1241 				'Emoticons'                            => __( 'Emoticons' ),
  1140 				'Nonbreaking space'                    => __( 'Nonbreaking space' ),
  1242 				'Nonbreaking space'                    => __( 'Nonbreaking space' ),
  1148 				'Horizontal space'                     => __( 'Horizontal space' ),
  1250 				'Horizontal space'                     => __( 'Horizontal space' ),
  1149 				'Restore last draft'                   => __( 'Restore last draft' ),
  1251 				'Restore last draft'                   => __( 'Restore last draft' ),
  1150 				'Insert/edit link'                     => array( __( 'Insert/edit link' ), 'metaK' ),
  1252 				'Insert/edit link'                     => array( __( 'Insert/edit link' ), 'metaK' ),
  1151 				'Remove link'                          => array( __( 'Remove link' ), 'accessS' ),
  1253 				'Remove link'                          => array( __( 'Remove link' ), 'accessS' ),
  1152 
  1254 
  1153 				// Link plugin
  1255 				// Link plugin.
  1154 				'Link'                                 => __( 'Link' ),
  1256 				'Link'                                 => __( 'Link' ),
  1155 				'Insert link'                          => __( 'Insert link' ),
  1257 				'Insert link'                          => __( 'Insert link' ),
  1156 				'Target'                               => __( 'Target' ),
  1258 				'Target'                               => __( 'Target' ),
  1157 				'New window'                           => __( 'New window' ),
  1259 				'New window'                           => __( 'New window' ),
  1158 				'Text to display'                      => __( 'Text to display' ),
  1260 				'Text to display'                      => __( 'Text to display' ),
  1162 				'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?' =>
  1264 				'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?' =>
  1163 					__( 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?' ),
  1265 					__( 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?' ),
  1164 
  1266 
  1165 				'Color'                                => __( 'Color' ),
  1267 				'Color'                                => __( 'Color' ),
  1166 				'Custom color'                         => __( 'Custom color' ),
  1268 				'Custom color'                         => __( 'Custom color' ),
  1167 				'Custom...'                            => _x( 'Custom...', 'label for custom color' ), // no ellipsis
  1269 				'Custom...'                            => _x( 'Custom...', 'label for custom color' ), // No ellipsis.
  1168 				'No color'                             => __( 'No color' ),
  1270 				'No color'                             => __( 'No color' ),
  1169 				'R'                                    => _x( 'R', 'Short for red in RGB' ),
  1271 				'R'                                    => _x( 'R', 'Short for red in RGB' ),
  1170 				'G'                                    => _x( 'G', 'Short for green in RGB' ),
  1272 				'G'                                    => _x( 'G', 'Short for green in RGB' ),
  1171 				'B'                                    => _x( 'B', 'Short for blue in RGB' ),
  1273 				'B'                                    => _x( 'B', 'Short for blue in RGB' ),
  1172 
  1274 
  1173 				// Spelling, search/replace plugins
  1275 				// Spelling, search/replace plugins.
  1174 				'Could not find the specified string.' => __( 'Could not find the specified string.' ),
  1276 				'Could not find the specified string.' => __( 'Could not find the specified string.' ),
  1175 				'Replace'                              => _x( 'Replace', 'find/replace' ),
  1277 				'Replace'                              => _x( 'Replace', 'find/replace' ),
  1176 				'Next'                                 => _x( 'Next', 'find/replace' ),
  1278 				'Next'                                 => _x( 'Next', 'find/replace' ),
  1177 				/* translators: previous */
  1279 				/* translators: Previous. */
  1178 				'Prev'                                 => _x( 'Prev', 'find/replace' ),
  1280 				'Prev'                                 => _x( 'Prev', 'find/replace' ),
  1179 				'Whole words'                          => _x( 'Whole words', 'find/replace' ),
  1281 				'Whole words'                          => _x( 'Whole words', 'find/replace' ),
  1180 				'Find and replace'                     => __( 'Find and replace' ),
  1282 				'Find and replace'                     => __( 'Find and replace' ),
  1181 				'Replace with'                         => _x( 'Replace with', 'find/replace' ),
  1283 				'Replace with'                         => _x( 'Replace with', 'find/replace' ),
  1182 				'Find'                                 => _x( 'Find', 'find/replace' ),
  1284 				'Find'                                 => _x( 'Find', 'find/replace' ),
  1186 				'Finish'                               => _x( 'Finish', 'spellcheck' ),
  1288 				'Finish'                               => _x( 'Finish', 'spellcheck' ),
  1187 				'Ignore all'                           => _x( 'Ignore all', 'spellcheck' ),
  1289 				'Ignore all'                           => _x( 'Ignore all', 'spellcheck' ),
  1188 				'Ignore'                               => _x( 'Ignore', 'spellcheck' ),
  1290 				'Ignore'                               => _x( 'Ignore', 'spellcheck' ),
  1189 				'Add to Dictionary'                    => __( 'Add to Dictionary' ),
  1291 				'Add to Dictionary'                    => __( 'Add to Dictionary' ),
  1190 
  1292 
  1191 				// TinyMCE tables
  1293 				// TinyMCE tables.
  1192 				'Insert table'                         => __( 'Insert table' ),
  1294 				'Insert table'                         => __( 'Insert table' ),
  1193 				'Delete table'                         => __( 'Delete table' ),
  1295 				'Delete table'                         => __( 'Delete table' ),
  1194 				'Table properties'                     => __( 'Table properties' ),
  1296 				'Table properties'                     => __( 'Table properties' ),
  1195 				'Row properties'                       => __( 'Table row properties' ),
  1297 				'Row properties'                       => __( 'Table row properties' ),
  1196 				'Cell properties'                      => __( 'Table cell properties' ),
  1298 				'Cell properties'                      => __( 'Table cell properties' ),
  1247 				'Background color'                     => __( 'Background color' ),
  1349 				'Background color'                     => __( 'Background color' ),
  1248 				'Text color'                           => __( 'Text color' ),
  1350 				'Text color'                           => __( 'Text color' ),
  1249 				'Show blocks'                          => _x( 'Show blocks', 'editor button' ),
  1351 				'Show blocks'                          => _x( 'Show blocks', 'editor button' ),
  1250 				'Show invisible characters'            => __( 'Show invisible characters' ),
  1352 				'Show invisible characters'            => __( 'Show invisible characters' ),
  1251 
  1353 
  1252 				/* translators: word count */
  1354 				/* translators: Word count. */
  1253 				'Words: {0}'                           => sprintf( __( 'Words: %s' ), '{0}' ),
  1355 				'Words: {0}'                           => sprintf( __( 'Words: %s' ), '{0}' ),
  1254 				'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' =>
  1356 				'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' =>
  1255 					__( 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' ) . "\n\n" .
  1357 					__( 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' ) . "\n\n" .
  1256 					__( 'If you&#8217;re looking to paste rich content from Microsoft Word, try turning this option off. The editor will clean up text pasted from Word automatically.' ),
  1358 					__( 'If you&#8217;re looking to paste rich content from Microsoft Word, try turning this option off. The editor will clean up text pasted from Word automatically.' ),
  1257 				'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help' =>
  1359 				'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help' =>
  1260 				'You have unsaved changes are you sure you want to navigate away?' =>
  1362 				'You have unsaved changes are you sure you want to navigate away?' =>
  1261 					__( 'The changes you made will be lost if you navigate away from this page.' ),
  1363 					__( 'The changes you made will be lost if you navigate away from this page.' ),
  1262 				'Your browser doesn\'t support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.' =>
  1364 				'Your browser doesn\'t support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.' =>
  1263 					__( 'Your browser does not support direct access to the clipboard. Please use keyboard shortcuts or your browser&#8217;s edit menu instead.' ),
  1365 					__( 'Your browser does not support direct access to the clipboard. Please use keyboard shortcuts or your browser&#8217;s edit menu instead.' ),
  1264 
  1366 
  1265 				// TinyMCE menus
  1367 				// TinyMCE menus.
  1266 				'Insert'                               => _x( 'Insert', 'TinyMCE menu' ),
  1368 				'Insert'                               => _x( 'Insert', 'TinyMCE menu' ),
  1267 				'File'                                 => _x( 'File', 'TinyMCE menu' ),
  1369 				'File'                                 => _x( 'File', 'TinyMCE menu' ),
  1268 				'Edit'                                 => _x( 'Edit', 'TinyMCE menu' ),
  1370 				'Edit'                                 => _x( 'Edit', 'TinyMCE menu' ),
  1269 				'Tools'                                => _x( 'Tools', 'TinyMCE menu' ),
  1371 				'Tools'                                => _x( 'Tools', 'TinyMCE menu' ),
  1270 				'View'                                 => _x( 'View', 'TinyMCE menu' ),
  1372 				'View'                                 => _x( 'View', 'TinyMCE menu' ),
  1271 				'Table'                                => _x( 'Table', 'TinyMCE menu' ),
  1373 				'Table'                                => _x( 'Table', 'TinyMCE menu' ),
  1272 				'Format'                               => _x( 'Format', 'TinyMCE menu' ),
  1374 				'Format'                               => _x( 'Format', 'TinyMCE menu' ),
  1273 
  1375 
  1274 				// WordPress strings
  1376 				// WordPress strings.
  1275 				'Toolbar Toggle'                       => array( __( 'Toolbar Toggle' ), 'accessZ' ),
  1377 				'Toolbar Toggle'                       => array( __( 'Toolbar Toggle' ), 'accessZ' ),
  1276 				'Insert Read More tag'                 => array( __( 'Insert Read More tag' ), 'accessT' ),
  1378 				'Insert Read More tag'                 => array( __( 'Insert Read More tag' ), 'accessT' ),
  1277 				'Insert Page Break tag'                => array( __( 'Insert Page Break tag' ), 'accessP' ),
  1379 				'Insert Page Break tag'                => array( __( 'Insert Page Break tag' ), 'accessP' ),
  1278 				'Read more...'                         => __( 'Read more...' ), // Title on the placeholder inside the editor (no ellipsis)
  1380 				'Read more...'                         => __( 'Read more...' ), // Title on the placeholder inside the editor (no ellipsis).
  1279 				'Distraction-free writing mode'        => array( __( 'Distraction-free writing mode' ), 'accessW' ),
  1381 				'Distraction-free writing mode'        => array( __( 'Distraction-free writing mode' ), 'accessW' ),
  1280 				'No alignment'                         => __( 'No alignment' ), // Tooltip for the 'alignnone' button in the image toolbar
  1382 				'No alignment'                         => __( 'No alignment' ), // Tooltip for the 'alignnone' button in the image toolbar.
  1281 				'Remove'                               => __( 'Remove' ), // Tooltip for the 'remove' button in the image toolbar
  1383 				'Remove'                               => __( 'Remove' ),       // Tooltip for the 'remove' button in the image toolbar.
  1282 				'Edit|button'                          => __( 'Edit' ), // Tooltip for the 'edit' button in the image toolbar
  1384 				'Edit|button'                          => __( 'Edit' ),         // Tooltip for the 'edit' button in the image toolbar.
  1283 				'Paste URL or type to search'          => __( 'Paste URL or type to search' ), // Placeholder for the inline link dialog
  1385 				'Paste URL or type to search'          => __( 'Paste URL or type to search' ), // Placeholder for the inline link dialog.
  1284 				'Apply'                                => __( 'Apply' ), // Tooltip for the 'apply' button in the inline link dialog
  1386 				'Apply'                                => __( 'Apply' ),        // Tooltip for the 'apply' button in the inline link dialog.
  1285 				'Link options'                         => __( 'Link options' ), // Tooltip for the 'link options' button in the inline link dialog
  1387 				'Link options'                         => __( 'Link options' ), // Tooltip for the 'link options' button in the inline link dialog.
  1286 				'Visual'                               => _x( 'Visual', 'Name for the Visual editor tab' ), // Editor switch tab label
  1388 				'Visual'                               => _x( 'Visual', 'Name for the Visual editor tab' ),             // Editor switch tab label.
  1287 				'Text'                                 => _x( 'Text', 'Name for the Text editor tab (formerly HTML)' ), // Editor switch tab label
  1389 				'Text'                                 => _x( 'Text', 'Name for the Text editor tab (formerly HTML)' ), // Editor switch tab label.
  1288 				'Add Media'                            => array( __( 'Add Media' ), 'accessM' ), // Tooltip for the 'Add Media' button in the Block Editor Classic block
  1390 				'Add Media'                            => array( __( 'Add Media' ), 'accessM' ), // Tooltip for the 'Add Media' button in the block editor Classic block.
  1289 
  1391 
  1290 				// Shortcuts help modal
  1392 				// Shortcuts help modal.
  1291 				'Keyboard Shortcuts'                   => array( __( 'Keyboard Shortcuts' ), 'accessH' ),
  1393 				'Keyboard Shortcuts'                   => array( __( 'Keyboard Shortcuts' ), 'accessH' ),
  1292 				'Classic Block Keyboard Shortcuts'     => __( 'Classic Block Keyboard Shortcuts' ),
  1394 				'Classic Block Keyboard Shortcuts'     => __( 'Classic Block Keyboard Shortcuts' ),
  1293 				'Default shortcuts,'                   => __( 'Default shortcuts,' ),
  1395 				'Default shortcuts,'                   => __( 'Default shortcuts,' ),
  1294 				'Additional shortcuts,'                => __( 'Additional shortcuts,' ),
  1396 				'Additional shortcuts,'                => __( 'Additional shortcuts,' ),
  1295 				'Focus shortcuts:'                     => __( 'Focus shortcuts:' ),
  1397 				'Focus shortcuts:'                     => __( 'Focus shortcuts:' ),
  1319 		Imagetools plugin (not included):
  1421 		Imagetools plugin (not included):
  1320 			'Edit image' => __( 'Edit image' ),
  1422 			'Edit image' => __( 'Edit image' ),
  1321 			'Image options' => __( 'Image options' ),
  1423 			'Image options' => __( 'Image options' ),
  1322 			'Back' => __( 'Back' ),
  1424 			'Back' => __( 'Back' ),
  1323 			'Invert' => __( 'Invert' ),
  1425 			'Invert' => __( 'Invert' ),
  1324 			'Flip horizontally' => __( 'Flip horizontally' ),
  1426 			'Flip horizontally' => __( 'Flip horizontal' ),
  1325 			'Flip vertically' => __( 'Flip vertically' ),
  1427 			'Flip vertically' => __( 'Flip vertical' ),
  1326 			'Crop' => __( 'Crop' ),
  1428 			'Crop' => __( 'Crop' ),
  1327 			'Orientation' => __( 'Orientation' ),
  1429 			'Orientation' => __( 'Orientation' ),
  1328 			'Resize' => __( 'Resize' ),
  1430 			'Resize' => __( 'Resize' ),
  1329 			'Rotate clockwise' => __( 'Rotate clockwise' ),
  1431 			'Rotate clockwise' => __( 'Rotate right' ),
  1330 			'Rotate counterclockwise' => __( 'Rotate counterclockwise' ),
  1432 			'Rotate counterclockwise' => __( 'Rotate left' ),
  1331 			'Sharpen' => __( 'Sharpen' ),
  1433 			'Sharpen' => __( 'Sharpen' ),
  1332 			'Brightness' => __( 'Brightness' ),
  1434 			'Brightness' => __( 'Brightness' ),
  1333 			'Color levels' => __( 'Color levels' ),
  1435 			'Color levels' => __( 'Color levels' ),
  1334 			'Contrast' => __( 'Contrast' ),
  1436 			'Contrast' => __( 'Contrast' ),
  1335 			'Gamma' => __( 'Gamma' ),
  1437 			'Gamma' => __( 'Gamma' ),
  1342 
  1444 
  1343 	/**
  1445 	/**
  1344 	 * Translates the default TinyMCE strings and returns them as JSON encoded object ready to be loaded with tinymce.addI18n(),
  1446 	 * Translates the default TinyMCE strings and returns them as JSON encoded object ready to be loaded with tinymce.addI18n(),
  1345 	 * or as JS snippet that should run after tinymce.js is loaded.
  1447 	 * or as JS snippet that should run after tinymce.js is loaded.
  1346 	 *
  1448 	 *
       
  1449 	 * @since 3.9.0
       
  1450 	 *
  1347 	 * @param string $mce_locale The locale used for the editor.
  1451 	 * @param string $mce_locale The locale used for the editor.
  1348 	 * @param bool $json_only optional Whether to include the JavaScript calls to tinymce.addI18n() and tinymce.ScriptLoader.markDone().
  1452 	 * @param bool   $json_only  Optional. Whether to include the JavaScript calls to tinymce.addI18n() and
       
  1453 	 *                           tinymce.ScriptLoader.markDone().
  1349 	 * @return string Translation object, JSON encoded.
  1454 	 * @return string Translation object, JSON encoded.
  1350 	 */
  1455 	 */
  1351 	public static function wp_mce_translation( $mce_locale = '', $json_only = false ) {
  1456 	public static function wp_mce_translation( $mce_locale = '', $json_only = false ) {
  1352 		if ( ! $mce_locale ) {
  1457 		if ( ! $mce_locale ) {
  1353 			$mce_locale = self::get_mce_locale();
  1458 			$mce_locale = self::get_mce_locale();
  1381 			if ( false !== strpos( $value, '&' ) ) {
  1486 			if ( false !== strpos( $value, '&' ) ) {
  1382 				$mce_translation[ $key ] = html_entity_decode( $value, ENT_QUOTES, 'UTF-8' );
  1487 				$mce_translation[ $key ] = html_entity_decode( $value, ENT_QUOTES, 'UTF-8' );
  1383 			}
  1488 			}
  1384 		}
  1489 		}
  1385 
  1490 
  1386 		// Set direction
  1491 		// Set direction.
  1387 		if ( is_rtl() ) {
  1492 		if ( is_rtl() ) {
  1388 			$mce_translation['_dir'] = 'rtl';
  1493 			$mce_translation['_dir'] = 'rtl';
  1389 		}
  1494 		}
  1390 
  1495 
  1391 		if ( $json_only ) {
  1496 		if ( $json_only ) {
  1402 	 * Force uncompressed TinyMCE when a custom theme has been defined.
  1507 	 * Force uncompressed TinyMCE when a custom theme has been defined.
  1403 	 *
  1508 	 *
  1404 	 * The compressed TinyMCE file cannot deal with custom themes, so this makes
  1509 	 * The compressed TinyMCE file cannot deal with custom themes, so this makes
  1405 	 * sure that we use the uncompressed TinyMCE file if a theme is defined.
  1510 	 * sure that we use the uncompressed TinyMCE file if a theme is defined.
  1406 	 * Even if we are on a production environment.
  1511 	 * Even if we are on a production environment.
       
  1512 	 *
       
  1513 	 * @since 5.0.0
  1407 	 */
  1514 	 */
  1408 	public static function force_uncompressed_tinymce() {
  1515 	public static function force_uncompressed_tinymce() {
  1409 		$has_custom_theme = false;
  1516 		$has_custom_theme = false;
  1410 		foreach ( self::$mce_settings as $init ) {
  1517 		foreach ( self::$mce_settings as $init ) {
  1411 			if ( ! empty( $init['theme_url'] ) ) {
  1518 			if ( ! empty( $init['theme_url'] ) ) {
  1427 	/**
  1534 	/**
  1428 	 * Print (output) the main TinyMCE scripts.
  1535 	 * Print (output) the main TinyMCE scripts.
  1429 	 *
  1536 	 *
  1430 	 * @since 4.8.0
  1537 	 * @since 4.8.0
  1431 	 *
  1538 	 *
  1432 	 * @global string $tinymce_version
  1539 	 * @global bool $concatenate_scripts
  1433 	 * @global bool   $concatenate_scripts
       
  1434 	 * @global bool   $compress_scripts
       
  1435 	 */
  1540 	 */
  1436 	public static function print_tinymce_scripts() {
  1541 	public static function print_tinymce_scripts() {
  1437 		global $concatenate_scripts;
  1542 		global $concatenate_scripts;
  1438 
  1543 
  1439 		if ( self::$tinymce_scripts_printed ) {
  1544 		if ( self::$tinymce_scripts_printed ) {
  1451 		echo "<script type='text/javascript'>\n" . self::wp_mce_translation() . "</script>\n";
  1556 		echo "<script type='text/javascript'>\n" . self::wp_mce_translation() . "</script>\n";
  1452 	}
  1557 	}
  1453 
  1558 
  1454 	/**
  1559 	/**
  1455 	 * Print (output) the TinyMCE configuration and initialization scripts.
  1560 	 * Print (output) the TinyMCE configuration and initialization scripts.
       
  1561 	 *
       
  1562 	 * @since 3.3.0
  1456 	 *
  1563 	 *
  1457 	 * @global string $tinymce_version
  1564 	 * @global string $tinymce_version
  1458 	 */
  1565 	 */
  1459 	public static function editor_js() {
  1566 	public static function editor_js() {
  1460 		global $tinymce_version;
  1567 		global $tinymce_version;
  1461 
  1568 
  1462 		$tmce_on = ! empty( self::$mce_settings );
  1569 		$tmce_on = ! empty( self::$mce_settings );
  1463 		$mceInit = $qtInit = '';
  1570 		$mceInit = '';
       
  1571 		$qtInit  = '';
  1464 
  1572 
  1465 		if ( $tmce_on ) {
  1573 		if ( $tmce_on ) {
  1466 			foreach ( self::$mce_settings as $editor_id => $init ) {
  1574 			foreach ( self::$mce_settings as $editor_id => $init ) {
  1467 				$options  = self::_parse_init( $init );
  1575 				$options  = self::_parse_init( $init );
  1468 				$mceInit .= "'$editor_id':{$options},";
  1576 				$mceInit .= "'$editor_id':{$options},";
  1523 
  1631 
  1524 		if ( $tmce_on ) {
  1632 		if ( $tmce_on ) {
  1525 			self::print_tinymce_scripts();
  1633 			self::print_tinymce_scripts();
  1526 
  1634 
  1527 			if ( self::$ext_plugins ) {
  1635 			if ( self::$ext_plugins ) {
  1528 				// Load the old-format English strings to prevent unsightly labels in old style popups
  1636 				// Load the old-format English strings to prevent unsightly labels in old style popups.
  1529 				echo "<script type='text/javascript' src='{$baseurl}/langs/wp-langs-en.js?$version'></script>\n";
  1637 				echo "<script type='text/javascript' src='{$baseurl}/langs/wp-langs-en.js?$version'></script>\n";
  1530 			}
  1638 			}
  1531 		}
  1639 		}
  1532 
  1640 
  1533 		/**
  1641 		/**
  1618 	 * Performs post queries for internal linking.
  1726 	 * Performs post queries for internal linking.
  1619 	 *
  1727 	 *
  1620 	 * @since 3.1.0
  1728 	 * @since 3.1.0
  1621 	 *
  1729 	 *
  1622 	 * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments.
  1730 	 * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments.
  1623 	 * @return false|array Results.
  1731 	 * @return array|false Results.
  1624 	 */
  1732 	 */
  1625 	public static function wp_link_query( $args = array() ) {
  1733 	public static function wp_link_query( $args = array() ) {
  1626 		$pts      = get_post_types( array( 'public' => true ), 'objects' );
  1734 		$pts      = get_post_types( array( 'public' => true ), 'objects' );
  1627 		$pt_names = array_keys( $pts );
  1735 		$pt_names = array_keys( $pts );
  1628 
  1736 
  1661 		$posts     = $get_posts->query( $query );
  1769 		$posts     = $get_posts->query( $query );
  1662 
  1770 
  1663 		// Build results.
  1771 		// Build results.
  1664 		$results = array();
  1772 		$results = array();
  1665 		foreach ( $posts as $post ) {
  1773 		foreach ( $posts as $post ) {
  1666 			if ( 'post' == $post->post_type ) {
  1774 			if ( 'post' === $post->post_type ) {
  1667 				$info = mysql2date( __( 'Y/m/d' ), $post->post_date );
  1775 				$info = mysql2date( __( 'Y/m/d' ), $post->post_date );
  1668 			} else {
  1776 			} else {
  1669 				$info = $pts[ $post->post_type ]->labels->singular_name;
  1777 				$info = $pts[ $post->post_type ]->labels->singular_name;
  1670 			}
  1778 			}
  1671 
  1779 
  1685 		 * @since 3.7.0
  1793 		 * @since 3.7.0
  1686 		 *
  1794 		 *
  1687 		 * @see 'wp_link_query_args' filter
  1795 		 * @see 'wp_link_query_args' filter
  1688 		 *
  1796 		 *
  1689 		 * @param array $results {
  1797 		 * @param array $results {
  1690 		 *     An associative array of query results.
  1798 		 *     An array of associative arrays of query results.
  1691 		 *
  1799 		 *
  1692 		 *     @type array {
  1800 		 *     @type array ...$0 {
  1693 		 *         @type int    $ID        Post ID.
  1801 		 *         @type int    $ID        Post ID.
  1694 		 *         @type string $title     The trimmed, escaped post title.
  1802 		 *         @type string $title     The trimmed, escaped post title.
  1695 		 *         @type string $permalink Post permalink.
  1803 		 *         @type string $permalink Post permalink.
  1696 		 *         @type string $info      A 'Y/m/d'-formatted date for 'post' post type,
  1804 		 *         @type string $info      A 'Y/m/d'-formatted date for 'post' post type,
  1697 		 *                                 the 'singular_name' post type label otherwise.
  1805 		 *                                 the 'singular_name' post type label otherwise.
  1708 	 * Dialog for internal linking.
  1816 	 * Dialog for internal linking.
  1709 	 *
  1817 	 *
  1710 	 * @since 3.1.0
  1818 	 * @since 3.1.0
  1711 	 */
  1819 	 */
  1712 	public static function wp_link_dialog() {
  1820 	public static function wp_link_dialog() {
  1713 		// Run once
  1821 		// Run once.
  1714 		if ( self::$link_dialog_printed ) {
  1822 		if ( self::$link_dialog_printed ) {
  1715 			return;
  1823 			return;
  1716 		}
  1824 		}
  1717 
  1825 
  1718 		self::$link_dialog_printed = true;
  1826 		self::$link_dialog_printed = true;
  1719 
  1827 
  1720 		// display: none is required here, see #WP27605
  1828 		// `display: none` is required here, see #WP27605.
  1721 		?>
  1829 		?>
  1722 		<div id="wp-link-backdrop" style="display: none"></div>
  1830 		<div id="wp-link-backdrop" style="display: none"></div>
  1723 		<div id="wp-link-wrap" class="wp-core-ui" style="display: none" role="dialog" aria-labelledby="link-modal-title">
  1831 		<div id="wp-link-wrap" class="wp-core-ui" style="display: none" role="dialog" aria-labelledby="link-modal-title">
  1724 		<form id="wp-link" tabindex="-1">
  1832 		<form id="wp-link" tabindex="-1">
  1725 		<?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?>
  1833 		<?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?>
  1763 					</div>
  1871 					</div>
  1764 					<ul></ul>
  1872 					<ul></ul>
  1765 					<div class="river-waiting">
  1873 					<div class="river-waiting">
  1766 						<span class="spinner"></span>
  1874 						<span class="spinner"></span>
  1767 					</div>
  1875 					</div>
  1768 				 </div>
  1876 				</div>
  1769 			 </div>
  1877 			</div>
  1770 		</div>
  1878 		</div>
  1771 		<div class="submitbox">
  1879 		<div class="submitbox">
  1772 			<div id="wp-link-cancel">
  1880 			<div id="wp-link-cancel">
  1773 				<button type="button" class="button"><?php _e( 'Cancel' ); ?></button>
  1881 				<button type="button" class="button"><?php _e( 'Cancel' ); ?></button>
  1774 			</div>
  1882 			</div>