WordPress.org

Make WordPress Core

Ticket #9798: spellchecker.patch

File spellchecker.patch, 14.3 KB (added by bforchhammer, 9 years ago)
  • wp-admin/includes/admin.php

     
    3333/** WordPress Post Administration API */
    3434require_once(ABSPATH . 'wp-admin/includes/post.php');
    3535
     36/** WordPress Spellchecking API */
     37require_once(ABSPATH . 'wp-admin/includes/spellchecker.php');
     38
    3639/** WordPress Taxonomy Administration API */
    3740require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
    3841
  • wp-admin/includes/class-wp-googlespell.php

     
     1<?php
     2/**
     3 * File contains a wordpress adapted version of TinyMCE's GoogleSpell class.
     4 *
     5 * @package WordPress
     6 * @author Benedikt Forchhammer <b.forchhammer@mind2.de>
     7 * @since       2.9.0
     8 */
     9
     10// The SpellChecking Engine that we want to extend
     11require_once( MCE_SPELLCHECKER_DIR . "/classes/GoogleSpell.php" );
     12
     13/**
     14 * Extension of TinyMCE GoogleSpell class for Wordpress
     15 *
     16 * WP_GoogleSpell extends TinyMCE's GoogleSpell class. It overrides the way in which the
     17 * http request to google is executed and uses wp_remote_post() instead of curl/fsockopen.
     18 *
     19 * @link http://trac.wordpress.org/ticket/9798 Request for proxy support for spellchecking
     20 * @since       2.9.0
     21 */
     22class WP_GoogleSpell extends GoogleSpell {
     23
     24        function &_getMatches($lang, $str) {
     25                if (function_exists('wp_remote_post')) {
     26                        // request url
     27                        $url = "https://www.google.com/tbproxy/spell?lang=" . $lang . "&hl=en";
     28                       
     29                        // Setup XML request
     30                        $xml = '<?xml version="1.0" encoding="utf-8" ?><spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1"><text>' . $str . '</text></spellrequest>';
     31                       
     32                        // set up request arguments.
     33                        $args = array( 'body' => $xml, 'sslverify' => false );
     34
     35                        // execute request and get response
     36                        $response = wp_remote_post($url, $args);
     37                       
     38                        if (is_wp_error($response)) {
     39                                wp_spellcheck_rpc_error(implode("\n", $response->get_error_messages()));
     40                        }
     41                        else {
     42                                // Grab and parse content
     43                                $matches = array();
     44                                preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', wp_remote_retrieve_body($response), $matches, PREG_SET_ORDER);
     45                       
     46                                return $matches;
     47                        }
     48                }
     49                else {
     50                        wp_spellcheck_rpc_error('wp_remote_post() function has not been loaded.');
     51                }
     52        }
     53       
     54        /**
     55         * Use wordpress function unhtmlentities()
     56         *
     57         * @see http://core.trac.wordpress.org/ticket/8689
     58         * @see http://core.trac.wordpress.org/ticket/9805
     59         */
     60        function _unhtmlentities($string) {
     61                if (function_exists('unhtmlentities')) return unhtmlentities($string);
     62                else return parent::_unhtmlentities($string);
     63        }
     64}
     65?>
     66 No newline at end of file
  • wp-admin/includes/post.php

     
    12991299                'theme_advanced_buttons4' => "$mce_buttons_4",
    13001300                'language' => "$mce_locale",
    13011301                'spellchecker_languages' => "$mce_spellchecker_languages",
     1302                'spellchecker_rpc_url' => get_bloginfo('url') . '/wp-admin/admin-ajax.php?action=spellcheck',
    13021303                'theme_advanced_toolbar_location' => 'top',
    13031304                'theme_advanced_toolbar_align' => 'left',
    13041305                'theme_advanced_statusbar_location' => 'bottom',
  • wp-admin/includes/spellchecker.php

     
     1<?php
     2/**
     3 * This File contains functions used to handle Ajax spellchecking requests.
     4 *
     5 * @package WordPress
     6 * @author      Benedikt Forchhammer <b.forchhammer@mind2.de>
     7 * @since       2.9.0
     8 */
     9
     10/**
     11 * Allows for the tinymce SpellChecker plugin directory to be moved from the default location.
     12 *
     13 * @since       2.9.0
     14 */
     15if ( !defined('MCE_SPELLCHECKER_DIR') )
     16        define( 'MCE_SPELLCHECKER_DIR', ABSPATH . WPINC . '/js/tinymce/plugins/spellchecker');
     17
     18add_action('wp_ajax_spellcheck', 'wp_spellcheck_ajax');
     19add_filter('wp_spellcheck_engine_config','wp_spellcheck_engine_replacements');
     20
     21/**
     22 * Changes config to use WP_GoogleSpell instead of GoogleSpell.
     23 *
     24 * @param       array   $config         Config array for SpellChecker
     25 * @since       2.9.0
     26 * @return      array
     27 */
     28function wp_spellcheck_engine_replacements($config) {
     29        // replace GoogleSpell with WP_GoogleSpell
     30        if ($config['general.engine'] == 'GoogleSpell') {
     31                $config['general.engine'] = 'WP_GoogleSpell';
     32                $config['general.engine.path'] =  ABSPATH . 'wp-admin/includes/class-wp-googlespell.php';
     33        }
     34        return $config;
     35}
     36
     37/**
     38 * Handle ajax request for "spellcheck" action.
     39 *
     40 * This function is called by the action hook "wp_ajax_spellcheck".
     41 *
     42 * @uses        apply_filters   wp_spellcheck_rpc_request
     43 * @uses        do_action               wp_spellcheck_rpc_result
     44 * @since       2.9.0
     45 * @return      void
     46 */
     47function wp_spellcheck_ajax() {
     48
     49        // set headers at this point so that they are set fatal error responses as well.
     50        wp_spellcheck_rpc_response_headers();
     51
     52        // get request data
     53        $request = wp_spellcheck_rpc_get_request();
     54        if (is_wp_error($request)) {
     55                wp_spellcheck_rpc_error($request->get_error_message());
     56        }
     57        $request = apply_filters('wp_spellcheck_rpc_request', $request);
     58       
     59        // execute and return spellcheck
     60        $result = wp_spellcheck_do_spellcheck($request['method'], $request['params']);
     61        if (is_wp_error($result)) {
     62                wp_spellcheck_rpc_error($result->get_error_message());
     63        }
     64        do_action_ref_array('wp_spellcheck_rpc_result', array( $request, &$result ));
     65       
     66        wp_spellcheck_rpc_send_response($request['id'], $result);
     67}
     68
     69/**
     70 * Calls a method on the SpellChecking Engine and returns the result.
     71 *
     72 * This function calls the method specified in $request['method']
     73 * with the parameters specified in $request['params'] on the configured
     74 * SpellChecker Engine.
     75 *
     76 * The two methods which are available by default are:
     77 *
     78 * <ul>
     79 * <li><strong>checkWords<strong>: checks an array of words for misspellings and returns array of misspelled words</li>
     80 * <li><strong>getSuggestions</strong>: retrieves a list of suggestions for a given misspelled word</li>
     81 * </ul>
     82 *
     83 * @param       string  $method         name of method
     84 * @param       array   $params         parameters
     85 * @since       2.9.0
     86 * @return      mixed   The spellchecking result or WP_Error object
     87 */
     88function wp_spellcheck_do_spellcheck ($method, $params = array()) {
     89        $spellchecker =& wp_spellcheck_get_engine();
     90       
     91        if (is_wp_error($spellchecker)) {
     92                return $spellchecker;
     93        }
     94       
     95        if (!is_object($spellchecker)) {
     96                return new WP_Error('wp-spellcheck-engine-null', __('Failed to get SpellChecker engine instance.'));
     97        }
     98               
     99        if (!method_exists($spellchecker, $method)) {
     100                // Either invalid method name or incomplete spellchecker class
     101                return new WP_Error('wp-spellcheck-engine-method-notfound', __('Failed to call method on spellchecking engine. '));
     102        }
     103       
     104        if (!is_array($params)) {
     105                $params = array($params);
     106        }
     107       
     108        $result = call_user_func_array(array($spellchecker, $method), $params);
     109       
     110        return $result;
     111}
     112
     113/**
     114 * Get spellcheck request data.
     115 *
     116 * @since       2.9.0
     117 * @return      mixed   
     118 */
     119function wp_spellcheck_rpc_get_request() {
     120
     121        // try to get raw data
     122        $raw = wp_spellcheck_rpc_raw_input();
     123        if (empty($raw)) {
     124                return new WP_Error("wp-spellcheck-request-empty", __("Could not get raw post data."));
     125        }
     126       
     127        // try to parse data as json
     128        $request = wp_spellcheck_json_decode($raw);
     129       
     130        // check we have good request data
     131        if (!is_array($request)) {
     132                return new WP_Error("wp-spellcheck-request-malformed", __("Failed parsing request as JSON: ") . print_r($request, 1) );
     133        }
     134        if (empty($request['method'])) {
     135                return new WP_Error("wp-spellcheck-request-malformed", __("Malformed JSON: missing \"method\" parameter."));
     136        }
     137        if (empty($request['params'])) {
     138                $request['params'] = array();
     139        }
     140       
     141        return $request;
     142}
     143
     144/**
     145 * Retrieves the raw request data for spellchecking request.
     146 *
     147 * The function tries the following sources and returns the
     148 * first non-empty one found:
     149 *
     150 * <ul>
     151 * <li>$_POST[json_data]</li>
     152 * <li>$_GLOBALS[HTTP_RAW_POST_DATA]</li>
     153 * <li>$HTTP_RAW_POST_DATA</li>
     154 * <li>file_get_contents("php://input")</li>
     155 * <li>fopen("php://input", "r");</li>
     156 * </ul>
     157 *
     158 * @link        http://core.trac.wordpress.org/browser/trunk/wp-includes/js/tinymce/plugins/spellchecker/rpc.php Roughly based on respective code in this file.
     159 * @since       2.9.0
     160 * @return      string Raw request data (json encoded)
     161 */
     162function wp_spellcheck_rpc_raw_input() {
     163        $raw = "";
     164
     165        // Try param
     166        if (isset($_POST["json_data"])) {
     167                $raw = $_POST["json_data"];
     168        }
     169
     170        // Try globals array
     171        if (!$raw && isset($_GLOBALS) && isset($_GLOBALS["HTTP_RAW_POST_DATA"])) {
     172                $raw = $_GLOBALS["HTTP_RAW_POST_DATA"];
     173        }
     174
     175        // Try globals variable
     176        if (!$raw && isset($HTTP_RAW_POST_DATA)) {
     177                $raw = $HTTP_RAW_POST_DATA;
     178        }
     179               
     180        // Try stream
     181        if (!$raw) {
     182                if (!function_exists('file_get_contents')) {
     183                        $fp = fopen("php://input", "r");
     184                        if ($fp) {
     185                                $raw = "";
     186
     187                                while (!feof($fp)) $raw = fread($fp, 1024);
     188                                fclose($fp);
     189                        }
     190                }
     191                else {
     192                        $raw = "" . file_get_contents("php://input");
     193                }
     194        }
     195
     196        return $raw;
     197}
     198
     199/**
     200 * Send the given result to client. This will stop all execution.
     201 *
     202 * @param       string  $id             Request id which was passed to the server in the request.
     203 * @param       array   $result Result of the request
     204 * @since       2.9.0
     205 * @return      void
     206 */
     207function wp_spellcheck_rpc_send_response($request_id, $result) {
     208
     209        // Request and response id should always be the same
     210        $output = array(
     211                "id" => $request_id,
     212                "result" => $result,
     213                "error" => null
     214        );
     215       
     216        // Return JSON encoded string
     217        echo wp_spellcheck_json_encode($output);
     218        exit();
     219}
     220
     221/**
     222 * Set headers for the spellcheck rpc response
     223 *
     224 * @uses        do_action       wp_spellcheck_rpc_headers
     225 * @since       2.9.0
     226 * @return      void
     227 */
     228function wp_spellcheck_rpc_response_headers() {
     229        header('Content-Type: text/plain');
     230        header('Content-Encoding: UTF-8');
     231        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
     232        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
     233        header("Cache-Control: no-store, no-cache, must-revalidate");
     234        header("Cache-Control: post-check=0, pre-check=0", false);
     235        header("Pragma: no-cache");     
     236       
     237        do_action('wp_spellcheck_rpc_headers');
     238}
     239
     240/**
     241 * Send json encoded error message to client. This will stop all execution.
     242 *
     243 * Note: this is a clone of TinyMCE's throwError() function in the
     244 * SpellChecker class (spellchecker plugin).
     245 *
     246 * @param       string  $msg    Message to send back to user.
     247 * @since       2.9.0
     248 * @return      void
     249 */
     250function wp_spellcheck_rpc_error($msg) {
     251        die('{"result":null,"id":null,"error":{"errstr":"' . addslashes($msg) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}');
     252}
     253
     254/**
     255 * Get the SpellChecker Engine Object
     256 *
     257 * @uses        apply_filters   wp_spellcheck_engine_class
     258 * @uses        apply_filters   wp_spellcheck_engine_path
     259 * @since       2.9.0
     260 * @return      SpellChecker    spell checking engine
     261 */
     262function &wp_spellcheck_get_engine() {
     263        static $spellchecker = null;
     264       
     265        if ($spellchecker === null) {
     266                // load base class for all spellcheckers
     267                if ( !class_exists('SpellChecker') ) {
     268                        require_once( MCE_SPELLCHECKER_DIR . "/classes/SpellChecker.php" );
     269                }
     270               
     271                $config = wp_spellcheck_get_engine_config();
     272               
     273                // get engine class name
     274                $engine_class = apply_filters('wp_spellcheck_engine_class', $config['general.engine']);
     275
     276                // try to load engine class if necessary
     277                if ( !class_exists($engine_class) ) {
     278
     279                        // determine engine file path
     280                        $engine_path = $config['general.engine.path'];
     281                        if (empty($engine_path)) {
     282                                $engine_path = MCE_SPELLCHECKER_DIR . "/classes/$engine_class.php";
     283                        }
     284                        $engine_path = apply_filters('wp_spellcheck_engine_path', $engine_path, $engine_class);
     285                       
     286                        if ( !file_exists($engine_path) ) {
     287                                return new WP_Error('wp-spellcheck-engine-not-found', __('Cannot load SpellChecker Engine; class file not found: ') . $engine_path );
     288                        }
     289                        require_once( $engine_path );
     290                       
     291                        if (!class_exists($engine_class)) {
     292                                return new WP_Error('wp-spellcheck-engine-not-found', __('Cannot load SpellChecker Engine; class not found: ') . $engine_class );
     293                        }
     294                }
     295               
     296                $spellchecker = new $engine_class($config);
     297        }
     298       
     299        return $spellchecker;
     300}
     301
     302/**
     303 * Get configuration values for the SpellChecker Engine.
     304 *
     305 * @uses        apply_filters   wp_spellcheck_engine_config
     306 * @since       2.9.0
     307 * @return      Array   array of config values
     308 */
     309function wp_spellcheck_get_engine_config() {
     310        $config = array();
     311        $config['general.engine'] = 'GoogleSpell';
     312       
     313        // load default tinymce config
     314        require_once( MCE_SPELLCHECKER_DIR . "/config.php" );
     315       
     316        return apply_filters('wp_spellcheck_engine_config', $config);
     317}
     318
     319/**
     320 * Encodes a php object into json
     321 *
     322 * @param       mixed   the thing to encode
     323 * @since       2.9.0
     324 * @return      string  json string
     325 */
     326function wp_spellcheck_json_encode($thing) {
     327        $json =& wp_spellcheck_json_object();
     328        return $json->encode($thing);
     329}
     330
     331/**
     332 * Decodes a json string into the respective php object
     333 *
     334 * @param       string  json string
     335 * @since       2.9.0
     336 * @return      mixed   json decoded thing
     337 */
     338function wp_spellcheck_json_decode($string) {
     339        $json =& wp_spellcheck_json_object();
     340        return $json->decode($string);
     341}
     342
     343/**
     344 * Returns an object of the moxiecode json encoder/transcoder class.
     345 *
     346 * @link http://core.trac.wordpress.org/browser/trunk/wp-includes/js/tinymce/plugins/spellchecker/classes/utils/JSON.php Moxiecode JSON Class
     347 * @since       2.9.0
     348 * @return      Moxiecode_JSON  JSON Encoder/Transcoder Object
     349 */
     350function &wp_spellcheck_json_object() {
     351        static $json = null;
     352        if ($json == null) {
     353                require_once( MCE_SPELLCHECKER_DIR . "/classes/utils/JSON.php" );
     354                $json = new Moxiecode_JSON();
     355        }
     356        return $json;
     357}
     358
     359?>
     360 No newline at end of file