WordPress.org

Make WordPress Core

Ticket #9798: spellcheck.patch

File spellcheck.patch, 14.1 KB (added by bforchhammer, 5 years ago)

Updated patch against current HEAD

  • wp-admin/admin-ajax.php

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