Mercurial > hg > rc2
comparison program/lib/Roundcube/rcube_spellcheck_enchant.php @ 0:4681f974d28b
vanilla 1.3.3 distro, I hope
| author | Charlie Root |
|---|---|
| date | Thu, 04 Jan 2018 15:52:31 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:4681f974d28b |
|---|---|
| 1 <?php | |
| 2 | |
| 3 /** | |
| 4 +-----------------------------------------------------------------------+ | |
| 5 | This file is part of the Roundcube Webmail client | | |
| 6 | | | |
| 7 | Copyright (C) 2011-2013, Kolab Systems AG | | |
| 8 | Copyright (C) 20011-2013, The Roundcube Dev Team | | |
| 9 | | | |
| 10 | Licensed under the GNU General Public License version 3 or | | |
| 11 | any later version with exceptions for skins & plugins. | | |
| 12 | See the README file for a full license statement. | | |
| 13 | | | |
| 14 | PURPOSE: | | |
| 15 | Spellchecking backend implementation to work with Enchant | | |
| 16 +-----------------------------------------------------------------------+ | |
| 17 | Author: Aleksander Machniak <machniak@kolabsys.com> | | |
| 18 +-----------------------------------------------------------------------+ | |
| 19 */ | |
| 20 | |
| 21 /** | |
| 22 * Spellchecking backend implementation to work with Pspell | |
| 23 * | |
| 24 * @package Framework | |
| 25 * @subpackage Utils | |
| 26 */ | |
| 27 class rcube_spellcheck_enchant extends rcube_spellcheck_engine | |
| 28 { | |
| 29 private $enchant_broker; | |
| 30 private $enchant_dictionary; | |
| 31 private $matches = array(); | |
| 32 | |
| 33 /** | |
| 34 * Return a list of languages supported by this backend | |
| 35 * | |
| 36 * @see rcube_spellcheck_engine::languages() | |
| 37 */ | |
| 38 function languages() | |
| 39 { | |
| 40 $this->init(); | |
| 41 | |
| 42 $langs = array(); | |
| 43 if ($dicts = enchant_broker_list_dicts($this->enchant_broker)) { | |
| 44 foreach ($dicts as $dict) { | |
| 45 $langs[] = preg_replace('/-.*$/', '', $dict['lang_tag']); | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 return array_unique($langs); | |
| 50 } | |
| 51 | |
| 52 /** | |
| 53 * Initializes Enchant dictionary | |
| 54 */ | |
| 55 private function init() | |
| 56 { | |
| 57 if (!$this->enchant_broker) { | |
| 58 if (!extension_loaded('enchant')) { | |
| 59 $this->error = "Enchant extension not available"; | |
| 60 return; | |
| 61 } | |
| 62 | |
| 63 $this->enchant_broker = enchant_broker_init(); | |
| 64 } | |
| 65 | |
| 66 if (!enchant_broker_dict_exists($this->enchant_broker, $this->lang)) { | |
| 67 $this->error = "Unable to load dictionary for selected language using Enchant"; | |
| 68 return; | |
| 69 } | |
| 70 | |
| 71 $this->enchant_dictionary = enchant_broker_request_dict($this->enchant_broker, $this->lang); | |
| 72 } | |
| 73 | |
| 74 /** | |
| 75 * Set content and check spelling | |
| 76 * | |
| 77 * @see rcube_spellcheck_engine::check() | |
| 78 */ | |
| 79 function check($text) | |
| 80 { | |
| 81 $this->init(); | |
| 82 | |
| 83 if (!$this->enchant_dictionary) { | |
| 84 return array(); | |
| 85 } | |
| 86 | |
| 87 // tokenize | |
| 88 $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); | |
| 89 | |
| 90 $diff = 0; | |
| 91 $matches = array(); | |
| 92 | |
| 93 foreach ($text as $w) { | |
| 94 $word = trim($w[0]); | |
| 95 $pos = $w[1] - $diff; | |
| 96 $len = mb_strlen($word); | |
| 97 | |
| 98 // skip exceptions | |
| 99 if ($this->dictionary->is_exception($word)) { | |
| 100 } | |
| 101 else if (!enchant_dict_check($this->enchant_dictionary, $word)) { | |
| 102 $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word); | |
| 103 | |
| 104 if (count($suggestions) > self::MAX_SUGGESTIONS) { | |
| 105 $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS); | |
| 106 } | |
| 107 | |
| 108 $matches[] = array($word, $pos, $len, null, $suggestions); | |
| 109 } | |
| 110 | |
| 111 $diff += (strlen($word) - $len); | |
| 112 } | |
| 113 | |
| 114 $this->matches = $matches; | |
| 115 return $matches; | |
| 116 } | |
| 117 | |
| 118 /** | |
| 119 * Returns suggestions for the specified word | |
| 120 * | |
| 121 * @see rcube_spellcheck_engine::get_words() | |
| 122 */ | |
| 123 function get_suggestions($word) | |
| 124 { | |
| 125 $this->init(); | |
| 126 | |
| 127 if (!$this->enchant_dictionary) { | |
| 128 return array(); | |
| 129 } | |
| 130 | |
| 131 $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word); | |
| 132 | |
| 133 if (count($suggestions) > self::MAX_SUGGESTIONS) | |
| 134 $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS); | |
| 135 | |
| 136 return is_array($suggestions) ? $suggestions : array(); | |
| 137 } | |
| 138 | |
| 139 /** | |
| 140 * Returns misspelled words | |
| 141 * | |
| 142 * @see rcube_spellcheck_engine::get_suggestions() | |
| 143 */ | |
| 144 function get_words($text = null) | |
| 145 { | |
| 146 $result = array(); | |
| 147 | |
| 148 if ($text) { | |
| 149 // init spellchecker | |
| 150 $this->init(); | |
| 151 | |
| 152 if (!$this->enchant_dictionary) { | |
| 153 return array(); | |
| 154 } | |
| 155 | |
| 156 // With Enchant we don't need to get suggestions to return misspelled words | |
| 157 $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); | |
| 158 | |
| 159 foreach ($text as $w) { | |
| 160 $word = trim($w[0]); | |
| 161 | |
| 162 // skip exceptions | |
| 163 if ($this->dictionary->is_exception($word)) { | |
| 164 continue; | |
| 165 } | |
| 166 | |
| 167 if (!enchant_dict_check($this->enchant_dictionary, $word)) { | |
| 168 $result[] = $word; | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 return $result; | |
| 173 } | |
| 174 | |
| 175 foreach ($this->matches as $m) { | |
| 176 $result[] = $m[0]; | |
| 177 } | |
| 178 | |
| 179 return $result; | |
| 180 } | |
| 181 } |
