public static function editor_settings($editor_id, $set) { $first_run = false; if (empty(self::$first_init)) { if (is_admin()) { add_action('admin_print_footer_scripts', array(__CLASS__, 'editor_js'), 50); add_action('admin_footer', array(__CLASS__, 'enqueue_scripts'), 1); } else { add_action('wp_print_footer_scripts', array(__CLASS__, 'editor_js'), 50); add_action('wp_footer', array(__CLASS__, 'enqueue_scripts'), 1); } } if (self::$this_quicktags) { $qtInit = array('id' => $editor_id, 'buttons' => ''); if (is_array($set['quicktags'])) { $qtInit = array_merge($qtInit, $set['quicktags']); } if (empty($qtInit['buttons'])) { $qtInit['buttons'] = 'strong,em,link,block,del,ins,img,ul,ol,li,code,more,close'; } if ($set['dfw']) { $qtInit['buttons'] .= ',fullscreen'; } /** * Filter the Quicktags settings. * * @since 3.3.0 * * @param array $qtInit Quicktags settings. * @param string $editor_id The unique editor ID, e.g. 'content'. */ $qtInit = apply_filters('quicktags_settings', $qtInit, $editor_id); self::$qt_settings[$editor_id] = $qtInit; self::$qt_buttons = array_merge(self::$qt_buttons, explode(',', $qtInit['buttons'])); } if (self::$this_tinymce) { if (empty(self::$first_init)) { self::$baseurl = includes_url('js/tinymce'); $mce_locale = get_locale(); self::$mce_locale = $mce_locale = empty($mce_locale) ? 'en' : strtolower(substr($mce_locale, 0, 2)); // ISO 639-1 /** This filter is documented in wp-admin/includes/media.php */ $no_captions = (bool) apply_filters('disable_captions', ''); $first_run = true; $ext_plugins = ''; if ($set['teeny']) { /** * Filter the list of teenyMCE plugins. * * @since 2.7.0 * * @param array $plugins An array of teenyMCE plugins. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ self::$plugins = $plugins = apply_filters('teeny_mce_plugins', array('fullscreen', 'image', 'wordpress', 'wpeditimage', 'wplink'), $editor_id); } else { /** * Filter the list of TinyMCE external plugins. * * The filter takes an associative array of external plugins for * TinyMCE in the form 'plugin_name' => 'url'. * * The url should be absolute, and should include the js filename * to be loaded. For example: * 'myplugin' => 'http://mysite.com/wp-content/plugins/myfolder/mce_plugin.js'. * * If the external plugin adds a button, it should be added with * one of the 'mce_buttons' filters. * * @since 2.5.0 * * @param array $external_plugins An array of external TinyMCE plugins. */ $mce_external_plugins = apply_filters('mce_external_plugins', array()); $plugins = array('charmap', 'hr', 'media', 'paste', 'tabfocus', 'textcolor', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs', 'wpview'); if (!self::$has_medialib) { $plugins[] = 'image'; } /** * Filter the list of default TinyMCE plugins. * * The filter specifies which of the default plugins included * in WordPress should be added to the TinyMCE instance. * * @since 3.3.0 * * @param array $plugins An array of default TinyMCE plugins. */ $plugins = array_unique(apply_filters('tiny_mce_plugins', $plugins)); if (($key = array_search('spellchecker', $plugins)) !== false) { // Remove 'spellchecker' from the internal plugins if added with 'tiny_mce_plugins' filter to prevent errors. // It can be added with 'mce_external_plugins'. unset($plugins[$key]); } if (!empty($mce_external_plugins)) { /** * Filter the translations loaded for external TinyMCE 3.x plugins. * * The filter takes an associative array ('plugin_name' => 'path') * where 'path' is the include path to the file. * * The language file should follow the same format as wp_mce_translation(), * and should define a variable ($strings) that holds all translated strings. * * @since 2.5.0 * * @param array $translations Translations for external TinyMCE plugins. */ $mce_external_languages = apply_filters('mce_external_languages', array()); $loaded_langs = array(); $strings = ''; if (!empty($mce_external_languages)) { foreach ($mce_external_languages as $name => $path) { if (@is_file($path) && @is_readable($path)) { include_once $path; $ext_plugins .= $strings . "\n"; $loaded_langs[] = $name; } } } foreach ($mce_external_plugins as $name => $url) { if (in_array($name, $plugins, true)) { unset($mce_external_plugins[$name]); continue; } $url = set_url_scheme($url); $mce_external_plugins[$name] = $url; $plugurl = dirname($url); $strings = $str1 = $str2 = ''; // Try to load langs/[locale].js and langs/[locale]_dlg.js if (!in_array($name, $loaded_langs, true)) { $path = str_replace(content_url(), '', $plugurl); $path = WP_CONTENT_DIR . $path . '/langs/'; if (function_exists('realpath')) { $path = trailingslashit(realpath($path)); } if (@is_file($path . $mce_locale . '.js')) { $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n"; } if (@is_file($path . $mce_locale . '_dlg.js')) { $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n"; } if ('en' != $mce_locale && empty($strings)) { if (@is_file($path . 'en.js')) { $str1 = @file_get_contents($path . 'en.js'); $strings .= preg_replace('/([\'"])en\\./', '$1' . $mce_locale . '.', $str1, 1) . "\n"; } if (@is_file($path . 'en_dlg.js')) { $str2 = @file_get_contents($path . 'en_dlg.js'); $strings .= preg_replace('/([\'"])en\\./', '$1' . $mce_locale . '.', $str2, 1) . "\n"; } } if (!empty($strings)) { $ext_plugins .= "\n" . $strings . "\n"; } } $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n"; $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n"; } } } if ($set['dfw']) { $plugins[] = 'wpfullscreen'; } self::$plugins = $plugins; self::$ext_plugins = $ext_plugins; self::$first_init = array('theme' => 'modern', 'skin' => 'lightgray', 'language' => self::$mce_locale, 'formats' => "{\n\t\t\t\t\t\talignleft: [\n\t\t\t\t\t\t\t{selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'left'}},\n\t\t\t\t\t\t\t{selector: 'img,table,dl.wp-caption', classes: 'alignleft'}\n\t\t\t\t\t\t],\n\t\t\t\t\t\taligncenter: [\n\t\t\t\t\t\t\t{selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'center'}},\n\t\t\t\t\t\t\t{selector: 'img,table,dl.wp-caption', classes: 'aligncenter'}\n\t\t\t\t\t\t],\n\t\t\t\t\t\talignright: [\n\t\t\t\t\t\t\t{selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles: {textAlign:'right'}},\n\t\t\t\t\t\t\t{selector: 'img,table,dl.wp-caption', classes: 'alignright'}\n\t\t\t\t\t\t],\n\t\t\t\t\t\tstrikethrough: {inline: 'del'}\n\t\t\t\t\t}", 'relative_urls' => false, 'remove_script_host' => false, 'convert_urls' => false, 'browser_spellcheck' => true, 'fix_list_elements' => true, 'entities' => '38,amp,60,lt,62,gt', 'entity_encoding' => 'raw', 'keep_styles' => false, 'paste_webkit_styles' => 'font-weight font-style color', 'preview_styles' => 'font-family font-size font-weight font-style text-decoration text-transform', 'wpeditimage_disable_captions' => $no_captions, 'wpeditimage_html5_captions' => current_theme_supports('html5', 'caption'), 'plugins' => implode(',', $plugins)); if (!empty($mce_external_plugins)) { self::$first_init['external_plugins'] = json_encode($mce_external_plugins); } $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; $version = 'ver=' . $GLOBALS['wp_version']; $dashicons = includes_url("css/dashicons{$suffix}.css?{$version}"); $mediaelement = includes_url("js/mediaelement/mediaelementplayer.min.css?{$version}"); $wpmediaelement = includes_url("js/mediaelement/wp-mediaelement.css?{$version}"); // WordPress default stylesheet and dashicons $mce_css = array($dashicons, $mediaelement, $wpmediaelement, self::$baseurl . '/skins/wordpress/wp-content.css?' . $version); // load editor_style.css if the current theme supports it if (!empty($GLOBALS['editor_styles']) && is_array($GLOBALS['editor_styles'])) { $editor_styles = $GLOBALS['editor_styles']; $editor_styles = array_unique(array_filter($editor_styles)); $style_uri = get_stylesheet_directory_uri(); $style_dir = get_stylesheet_directory(); // Support externally referenced styles (like, say, fonts). foreach ($editor_styles as $key => $file) { if (preg_match('~^(https?:)?//~', $file)) { $mce_css[] = esc_url_raw($file); unset($editor_styles[$key]); } } // Look in a parent theme first, that way child theme CSS overrides. if (is_child_theme()) { $template_uri = get_template_directory_uri(); $template_dir = get_template_directory(); foreach ($editor_styles as $key => $file) { if ($file && file_exists("{$template_dir}/{$file}")) { $mce_css[] = "{$template_uri}/{$file}"; } } } foreach ($editor_styles as $file) { if ($file && file_exists("{$style_dir}/{$file}")) { $mce_css[] = "{$style_uri}/{$file}"; } } } /** * Filter the comma-delimited list of stylesheets to load in TinyMCE. * * @since 2.1.0 * * @param array $stylesheets Comma-delimited list of stylesheets. */ $mce_css = trim(apply_filters('mce_css', implode(',', $mce_css)), ' ,'); if (!empty($mce_css)) { self::$first_init['content_css'] = $mce_css; } } if ($set['teeny']) { /** * Filter the list of teenyMCE buttons (Text tab). * * @since 2.7.0 * * @param array $buttons An array of teenyMCE buttons. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mce_buttons = apply_filters('teeny_mce_buttons', array('bold', 'italic', 'underline', 'blockquote', 'strikethrough', 'bullist', 'numlist', 'alignleft', 'aligncenter', 'alignright', 'undo', 'redo', 'link', 'unlink', 'fullscreen'), $editor_id); $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = array(); } else { /** * Filter the first-row list of TinyMCE buttons (Visual tab). * * @since 2.0.0 * * @param array $buttons First-row list of buttons. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'bullist', 'numlist', 'blockquote', 'hr', 'alignleft', 'aligncenter', 'alignright', 'link', 'unlink', 'wp_more', 'spellchecker', 'fullscreen', 'wp_adv'), $editor_id); /** * Filter the second-row list of TinyMCE buttons (Visual tab). * * @since 2.0.0 * * @param array $buttons Second-row list of buttons. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mce_buttons_2 = apply_filters('mce_buttons_2', array('formatselect', 'underline', 'alignjustify', 'forecolor', 'pastetext', 'removeformat', 'charmap', 'outdent', 'indent', 'undo', 'redo', 'wp_help'), $editor_id); /** * Filter the third-row list of TinyMCE buttons (Visual tab). * * @since 2.0.0 * * @param array $buttons Third-row list of buttons. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mce_buttons_3 = apply_filters('mce_buttons_3', array(), $editor_id); /** * Filter the fourth-row list of TinyMCE buttons (Visual tab). * * @since 2.5.0 * * @param array $buttons Fourth-row list of buttons. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mce_buttons_4 = apply_filters('mce_buttons_4', array(), $editor_id); } $body_class = $editor_id; if ($post = get_post()) { $body_class .= ' post-type-' . sanitize_html_class($post->post_type) . ' post-status-' . sanitize_html_class($post->post_status); if (post_type_supports($post->post_type, 'post-formats')) { $post_format = get_post_format($post); if ($post_format && !is_wp_error($post_format)) { $body_class .= ' post-format-' . sanitize_html_class($post_format); } else { $body_class .= ' post-format-standard'; } } } if (!empty($set['tinymce']['body_class'])) { $body_class .= ' ' . $set['tinymce']['body_class']; unset($set['tinymce']['body_class']); } if ($set['dfw']) { // replace the first 'fullscreen' with 'wp_fullscreen' if (($key = array_search('fullscreen', $mce_buttons)) !== false) { $mce_buttons[$key] = 'wp_fullscreen'; } elseif (($key = array_search('fullscreen', $mce_buttons_2)) !== false) { $mce_buttons_2[$key] = 'wp_fullscreen'; } elseif (($key = array_search('fullscreen', $mce_buttons_3)) !== false) { $mce_buttons_3[$key] = 'wp_fullscreen'; } elseif (($key = array_search('fullscreen', $mce_buttons_4)) !== false) { $mce_buttons_4[$key] = 'wp_fullscreen'; } } $mceInit = array('selector' => "#{$editor_id}", 'resize' => 'vertical', 'menubar' => false, 'wpautop' => (bool) $set['wpautop'], 'indent' => !$set['wpautop'], 'toolbar1' => implode($mce_buttons, ','), 'toolbar2' => implode($mce_buttons_2, ','), 'toolbar3' => implode($mce_buttons_3, ','), 'toolbar4' => implode($mce_buttons_4, ','), 'tabfocus_elements' => $set['tabfocus_elements'], 'body_class' => $body_class); if ($first_run) { $mceInit = array_merge(self::$first_init, $mceInit); } if (is_array($set['tinymce'])) { $mceInit = array_merge($mceInit, $set['tinymce']); } /* * For people who really REALLY know what they're doing with TinyMCE * You can modify $mceInit to add, remove, change elements of the config * before tinyMCE.init. Setting "valid_elements", "invalid_elements" * and "extended_valid_elements" can be done through this filter. Best * is to use the default cleanup by not specifying valid_elements, * as TinyMCE contains full set of XHTML 1.0. */ if ($set['teeny']) { /** * Filter the teenyMCE config before init. * * @since 2.7.0 * * @param array $mceInit An array with teenyMCE config. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mceInit = apply_filters('teeny_mce_before_init', $mceInit, $editor_id); } else { /** * Filter the TinyMCE config before init. * * @since 2.5.0 * * @param array $mceInit An array with TinyMCE config. * @param string $editor_id Unique editor identifier, e.g. 'content'. */ $mceInit = apply_filters('tiny_mce_before_init', $mceInit, $editor_id); } if (empty($mceInit['toolbar3']) && !empty($mceInit['toolbar4'])) { $mceInit['toolbar3'] = $mceInit['toolbar4']; $mceInit['toolbar4'] = ''; } self::$mce_settings[$editor_id] = $mceInit; } // end if self::$this_tinymce }