: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$mce_translation['_dir'] = 'rtl';
return wp_json_encode( $mce_translation );
$baseurl = self::get_baseurl();
return "tinymce.addI18n( '$mce_locale', " . wp_json_encode( $mce_translation ) . ");\n" .
"tinymce.ScriptLoader.markDone( '$baseurl/langs/$mce_locale.js' );\n";
* Force uncompressed TinyMCE when a custom theme has been defined.
* The compressed TinyMCE file cannot deal with custom themes, so this makes
* sure that WordPress uses the uncompressed TinyMCE file if a theme is defined.
* Even if the website is running on a production environment.
public static function force_uncompressed_tinymce() {
$has_custom_theme = false;
foreach ( self::$mce_settings as $init ) {
if ( ! empty( $init['theme_url'] ) ) {
$has_custom_theme = true;
if ( ! $has_custom_theme ) {
$wp_scripts = wp_scripts();
$wp_scripts->remove( 'wp-tinymce' );
wp_register_tinymce_scripts( $wp_scripts, true );
* Print (output) the main TinyMCE scripts.
* @global bool $concatenate_scripts
public static function print_tinymce_scripts() {
global $concatenate_scripts;
if ( self::$tinymce_scripts_printed ) {
self::$tinymce_scripts_printed = true;
if ( ! isset( $concatenate_scripts ) ) {
script_concat_settings();
wp_print_scripts( array( 'wp-tinymce' ) );
echo "<script type='text/javascript'>\n" . self::wp_mce_translation() . "</script>\n";
* Print (output) the TinyMCE configuration and initialization scripts.
* @global string $tinymce_version
public static function editor_js() {
$tmce_on = ! empty( self::$mce_settings );
foreach ( self::$mce_settings as $editor_id => $init ) {
$options = self::_parse_init( $init );
$mce_init .= "'$editor_id':{$options},";
$mce_init = '{' . trim( $mce_init, ',' ) . '}';
if ( ! empty( self::$qt_settings ) ) {
foreach ( self::$qt_settings as $editor_id => $init ) {
$options = self::_parse_init( $init );
$qt_init .= "'$editor_id':{$options},";
$qt_init = '{' . trim( $qt_init, ',' ) . '}';
'plugins' => implode( ',', self::$plugins ),
'language' => self::$mce_locale,
$suffix = SCRIPT_DEBUG ? '' : '.min';
$baseurl = self::get_baseurl();
$version = 'ver=' . $tinymce_version;
* Fires immediately before the TinyMCE settings are printed.
* @param array $mce_settings TinyMCE settings array.
do_action( 'before_wp_tiny_mce', self::$mce_settings );
<script type="text/javascript">
baseURL: "<?php echo $baseurl; ?>",
suffix: "<?php echo $suffix; ?>",
if ( self::$drag_drop_upload ) {
echo 'dragDropUpload: true,';
mceInit: <?php echo $mce_init; ?>,
qtInit: <?php echo $qt_init; ?>,
ref: <?php echo self::_parse_init( $ref ); ?>,
load_ext: function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
self::print_tinymce_scripts();
if ( self::$ext_plugins ) {
// Load the old-format English strings to prevent unsightly labels in old style popups.
echo "<script type='text/javascript' src='{$baseurl}/langs/wp-langs-en.js?$version'></script>\n";
* Fires after tinymce.js is loaded, but before any TinyMCE editor
* @param array $mce_settings TinyMCE settings array.
do_action( 'wp_tiny_mce_init', self::$mce_settings );
<script type="text/javascript">
if ( self::$ext_plugins ) {
echo self::$ext_plugins . "\n";
echo 'var ajaxurl = "' . admin_url( 'admin-ajax.php', 'relative' ) . '";';
var initialize = function() {
var init, id, inPostbox, $wrap;
var readyState = document.readyState;
if ( readyState !== 'complete' && readyState !== 'interactive' ) {
for ( id in tinyMCEPreInit.mceInit ) {
if ( initialized.indexOf( id ) > -1 ) {
init = tinyMCEPreInit.mceInit[id];
$wrap = tinymce.$( '#wp-' + id + '-wrap' );
inPostbox = $wrap.parents( '.postbox' ).length > 0;
( $wrap.hasClass( 'tmce-active' ) || ! tinyMCEPreInit.qtInit.hasOwnProperty( id ) ) &&
( readyState === 'complete' || ( ! inPostbox && readyState === 'interactive' ) )
if ( ! window.wpActiveEditor ) {
window.wpActiveEditor = id;
if ( typeof tinymce !== 'undefined' ) {
if ( tinymce.Env.ie && tinymce.Env.ie < 11 ) {
tinymce.$( '.wp-editor-wrap ' ).removeClass( 'tmce-active' ).addClass( 'html-active' );
if ( document.readyState === 'complete' ) {
document.addEventListener( 'readystatechange', initialize );
if ( typeof quicktags !== 'undefined' ) {
for ( id in tinyMCEPreInit.qtInit ) {
quicktags( tinyMCEPreInit.qtInit[id] );
if ( ! window.wpActiveEditor ) {
window.wpActiveEditor = id;
if ( in_array( 'wplink', self::$plugins, true ) || in_array( 'link', self::$qt_buttons, true ) ) {
* Fires after any core TinyMCE editor instances are created.
* @param array $mce_settings TinyMCE settings array.
do_action( 'after_wp_tiny_mce', self::$mce_settings );
* Outputs the HTML for distraction-free writing mode.
public static function wp_fullscreen_html() {
_deprecated_function( __FUNCTION__, '4.3.0' );
* Performs post queries for internal linking.
* Optional. Array of link query arguments.
* @type int $pagenum Page number. Default 1.
* @type string $s Search keywords.
* @return array|false $results {
* An array of associative arrays of query results, false if there are none.
* @type string $title The trimmed, escaped post title.
* @type string $permalink Post permalink.
* @type string $info A 'Y/m/d'-formatted date for 'post' post type,
* the 'singular_name' post type label otherwise.
public static function wp_link_query( $args = array() ) {
$pts = get_post_types( array( 'public' => true ), 'objects' );
$pt_names = array_keys( $pts );
'post_type' => $pt_names,
'suppress_filters' => true,
'update_post_term_cache' => false,
'update_post_meta_cache' => false,
'post_status' => 'publish',
$args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1;
if ( isset( $args['s'] ) ) {
$query['s'] = $args['s'];
$query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0;
* Filters the link query arguments.
* Allows modification of the link query arguments before querying.
* @see WP_Query for a full list of arguments
* @param array $query An array of WP_Query arguments.
$query = apply_filters( 'wp_link_query_args', $query );
$get_posts = new WP_Query();
$posts = $get_posts->query( $query );
foreach ( $posts as $post ) {
if ( 'post' === $post->post_type ) {
$info = mysql2date( __( 'Y/m/d' ), $post->post_date );
$info = $pts[ $post->post_type ]->labels->singular_name;
'title' => trim( esc_html( strip_tags( get_the_title( $post ) ) ) ),
'permalink' => get_permalink( $post->ID ),
* Filters the link query results.
* Allows modification of the returned link query results.
* @see 'wp_link_query_args' filter
* @param array $results {
* An array of associative arrays of query results.
* @type string $title The trimmed, escaped post title.
* @type string $permalink Post permalink.
* @type string $info A 'Y/m/d'-formatted date for 'post' post type,
* the 'singular_name' post type label otherwise.
* @param array $query An array of WP_Query arguments.
$results = apply_filters( 'wp_link_query', $results, $query );
return ! empty( $results ) ? $results : false;
* Dialog for internal linking.
public static function wp_link_dialog() {
if ( self::$link_dialog_printed ) {
self::$link_dialog_printed = true;
// `display: none` is required here, see #WP27605.
<div id="wp-link-backdrop" style="display: none"></div>
<div id="wp-link-wrap" class="wp-core-ui" style="display: none" role="dialog" aria-modal="true" aria-labelledby="link-modal-title">
<form id="wp-link" tabindex="-1">
<?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?>
<h1 id="link-modal-title"><?php _e( 'Insert/edit link' ); ?></h1>
<button type="button" id="wp-link-close"><span class="screen-reader-text">
/* translators: Hidden accessibility text. */
<p class="howto" id="wplink-enter-url"><?php _e( 'Enter the destination URL' ); ?></p>
<label><span><?php _e( 'URL' ); ?></span>
<input id="wp-link-url" type="text" aria-describedby="wplink-enter-url" /></label>
<div class="wp-link-text-field">
<label><span><?php _e( 'Link Text' ); ?></span>
<input id="wp-link-text" type="text" /></label>
<div class="link-target">
<input type="checkbox" id="wp-link-target" /> <?php _e( 'Open link in a new tab' ); ?></label>
<p class="howto" id="wplink-link-existing-content"><?php _e( 'Or link to existing content' ); ?></p>
<div class="link-search-wrapper">
<span class="search-label"><?php _e( 'Search' ); ?></span>
<input type="search" id="wp-link-search" class="link-search-field" autocomplete="off" aria-describedby="wplink-link-existing-content" />
<span class="spinner"></span>
<div id="search-results" class="query-results" tabindex="0">
<div class="river-waiting">
<span class="spinner"></span>
<div id="most-recent-results" class="query-results" tabindex="0">
<div class="query-notice" id="query-notice-message">
<em class="query-notice-default"><?php _e( 'No search term specified. Showing recent items.' ); ?></em>
<em class="query-notice-hint screen-reader-text">
/* translators: Hidden accessibility text. */
_e( 'Search or use up and down arrow keys to select an item.' );
<div class="river-waiting">
<span class="spinner"></span>
<div id="wp-link-cancel">
<button type="button" class="button"><?php _e( 'Cancel' ); ?></button>
<div id="wp-link-update">
<input type="submit" value="<?php esc_attr_e( 'Add Link' ); ?>" class="button button-primary" id="wp-link-submit" name="wp-link-submit">