You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rcube_spellcheck_enchant.php 5.3KB

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