Thomas
2013-10-14 566747af00ae413c942a7c6702e24c044af36f17
commit | author | age
bc0a47 1 <?php
TB 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     /**
c344b6 34      * Return a list of languages supported by this backend
TB 35      *
36      * @see rcube_spellcheck_engine::languages()
37      */
38     function languages()
39     {
40         $this->init();
41
42         $langs = array();
43         $dicts = enchant_broker_list_dicts($this->enchant_broker);
44         foreach ($dicts as $dict) {
45             $langs[] = preg_replace('/-.*$/', '', $dict['lang_tag']);
46         }
47
48         return array_unique($langs);
49     }
50
51     /**
bc0a47 52      * Initializes Enchant dictionary
TB 53      */
54     private function init()
55     {
56         if (!$this->enchant_broker) {
57             if (!extension_loaded('enchant')) {
58                 $this->error = "Enchant extension not available";
59                 return;
60             }
61
62             $this->enchant_broker = enchant_broker_init();
63         }
64
65         if (!enchant_broker_dict_exists($this->enchant_broker, $this->lang)) {
66             $this->error = "Unable to load dictionary for selected language using Enchant";
67             return;
68         }
69
70         $this->enchant_dictionary = enchant_broker_request_dict($this->enchant_broker, $this->lang);
71     }
72
73     /**
74      * Set content and check spelling
75      *
76      * @see rcube_spellcheck_engine::check()
77      */
78     function check($text)
79     {
80         $this->init();
81
82         if (!$this->enchant_dictionary) {
83             return array();
84         }
85
86         // tokenize
87         $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
88
89         $diff       = 0;
90         $matches    = array();
91
92         foreach ($text as $w) {
93             $word = trim($w[0]);
94             $pos  = $w[1] - $diff;
95             $len  = mb_strlen($word);
96
97             // skip exceptions
98             if ($this->dictionary->is_exception($word)) {
99             }
100             else if (!enchant_dict_check($this->enchant_dictionary, $word)) {
101                 $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word);
102
103                 if (sizeof($suggestions) > self::MAX_SUGGESTIONS) {
104                     $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
105                 }
106
107                 $matches[] = array($word, $pos, $len, null, $suggestions);
108             }
109
110             $diff += (strlen($word) - $len);
111         }
112
113         $this->matches = $matches;
114         return $matches;
115     }
116
117     /**
118      * Returns suggestions for the specified word
119      *
120      * @see rcube_spellcheck_engine::get_words()
121      */
122     function get_suggestions($word)
123     {
124         $this->init();
125
126         if (!$this->enchant_dictionary) {
127             return array();
128         }
129
130         $suggestions = enchant_dict_suggest($this->enchant_dictionary, $word);
131
132         if (sizeof($suggestions) > self::MAX_SUGGESTIONS)
133             $suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
134
135         return is_array($suggestions) ? $suggestions : array();
136     }
137
138     /**
139      * Returns misspelled words
140      *
141      * @see rcube_spellcheck_engine::get_suggestions()
142      */
143     function get_words($text = null)
144     {
145         $result = array();
146
147         if ($text) {
148             // init spellchecker
149             $this->init();
150
151             if (!$this->enchant_dictionary) {
152                 return array();
153             }
154
155             // With Enchant we don't need to get suggestions to return misspelled words
156             $text = preg_split($this->separator, $text, NULL, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
157
158             foreach ($text as $w) {
159                 $word = trim($w[0]);
160
161                 // skip exceptions
162                 if ($this->dictionary->is_exception($word)) {
163                     continue;
164                 }
165
166                 if (!enchant_dict_check($this->enchant_dictionary, $word)) {
167                     $result[] = $word;
168                 }
169             }
170
171             return $result;
172         }
173
174         foreach ($this->matches as $m) {
175             $result[] = $m[0];
176         }
177
178         return $result;
179     }
180
181 }
182