] // The word list to be checked private $_words; // $_dic [Array] // The array that mimic the dictionary. It can be more // sophisticated. However, this is only a demo. private $_dic; // SIMI [Number] // The threshold of the similarity const SIMI = 0.6; public function __construct(){ $this->_dic = explode("\n", file_get_contents($this->fileName)); } public function setLanguage($lang){ $this->_lang = $lang; } public function setEncoding($encoding){ $this->_encoding = $encoding; } public function setWords($words){ $this->_words = $words; } public function add($word){ $handle = fopen($this->fileName, 'a'); fwrite($handle, "$word\n"); fclose($handle); return "{response:[]}"; } public function check(){ // summary: // Check the spelling and return a HTML page with a JSON string like // {response: [ // { // text :"teest", // suggestion:["test","treat"] // } // ]} if($this->_lang == "EN"){ $len = count($this->_words); for($i = 0; $i < $len; $i++){ $this->_words[$i]->suggestion = $this->lookup($this->_words[$i]->text); } $temp = array(); for($i = 0; $i < $len; $i++){ if($this->_words[$i]->suggestion !== NULL){ array_push($temp, $this->_words[$i]); } } return "{response:" . json_encode($temp). "}"; }else{ // This is only a demo, so keep the text as-is // if the encoding is not UTF-8 or the language is // not English return "{response:[]}"; // No spelling error found } } private function lookup($word){ // summary: // Look for the given word. If it is not found, a suggestion list // will be returned, else an empty list will be returned. $len = count($this->_dic); $lst = array(); for($i = 0; $i < $len; $i++){ if($word == $this->_dic[$i] || PorterStemmer::getStem($word) == $this->_dic[$i]){ return NULL; }else{ // Compare the two words to get the similarity. $num = $this->_lcs($word, $this->_dic[$i]); if($num / strlen($word) > self::SIMI && $num / strlen($this->_dic[$i]) > self::SIMI){ array_push($lst, $this->_dic[$i]); } } } return $lst; } private function _lcs($word1, $word2){ // summary: // Longest Common Subsequence /* $f[$i][$j] = max(f[$i-1][$j-1] + same($i, $j), f[$i-1][$j], f[$i][$j-1];*/ $len1 = strlen($word1); $len2 = strlen($word2); for($i = 0; $i <= $len1; $i++){ $f[$i][0] = 0; } for($j = 0; $j <= $len2; $j++){ $f[0][$j] = 0; } for($i = 1; $i <= $len1; $i++){ for($j = 1; $j <= $len2; $j++){ $f[$i][$j] = max($f[$i - 1][$j - 1] + ($word1[$i - 1] == $word2[$j - 1] ? 1 : 0), max($f[$i - 1][$j], $f[$i][$j - 1])); } } return $f[$i - 1][$j - 1]; } } function text2Words($text){ $result = array(); $words = explode (" ", $text); $len = count($words); for($i = 0; $i < $len; $i++){ $word = new Word(); $word->text = $words[$i]; array_push($result, $word); } return $result; } header('Content-Type: text/html; charset=UTF-8'); $sourceText = array_key_exists("content", $_REQUEST) ? $_REQUEST["content"] : ""; $lang = array_key_exists("lang", $_REQUEST) ? $_REQUEST["lang"] : "EN"; $action = array_key_exists("action", $_REQUEST) ? $_REQUEST["action"] : "query"; $callback = array_key_exists("callback", $_REQUEST) ? $_REQUEST["callback"] : "callback"; $dic = new SpellDic(); $dic->setLanguage($lang); if($action == "query"){ $dic->setWords(text2Words(trim($sourceText))); echo "$callback(" . $dic->check() . ");"; // JSONP Specification }else if ($action == "update"){ echo "$callback(" . $dic->add($sourceText) . ");"; } ?>