4 * Copyright 2006,2007 $ThePhpWikiProgrammingTeam
6 * This file is part of PhpWiki.
8 * PhpWiki is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * PhpWiki is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * SpellCheck is a plugin, used inside the editpage.tmpl (on save or preview)
25 * This could be a userpref option always highlighting words in preview
26 * or it could be an extra button in edit.
28 * The pspell extension is better, because it's easier to store corrections.
29 * Enchant looks more promising, because it supports multiple speller backends.
31 * Currently we do use aspell (via pspell or cmdline) in ispell mode.
32 * Maybe enchant later.
33 * cmdline preparation:
34 do autosplit wikiwords && sed s,^,\^^, $pagename | aspell --lang=$LANG -a
36 sed s,^,\^^, $pagename | aspell --lang=$LANG -a -C
38 & phpwiki 62 30: pipework, paprika, Popek, Phip, Pike, Viki, pike, ...
41 // Those settings should really be defined in config.ini, not here.
42 if (!function_exists('pspell_new_config')) {
43 // old pipe interface:
44 if (!defined('ASPELL_EXE'))
45 define('ASPELL_EXE','aspell');
46 //define('ASPELL_EXE','/usr/local/bin/aspell');
47 //define('ASPELL_EXE','/home/groups/p/ph/phpwiki/bin/aspell');
48 if (!defined('ASPELL_DATA_DIR'))
50 define('ASPELL_DATA_DIR','c:\cygwin\usr\share\aspell');
52 define('ASPELL_DATA_DIR','/usr/share/aspell');
53 //define('ASPELL_DATA_DIR','/home/groups/p/ph/phpwiki/share/highlight');
55 // new library interface through the pspell extension:
56 // "/var/dictionaries/custom.pws"
57 if (!defined('PSPELL_PWL'))
58 define('PSPELL_PWL', ''); // phpwiki-special wordlist
59 // "/var/dictionaries/custom.repl"
60 if (!defined('PSPELL_REPL'))
61 define('PSPELL_REPL', ''); // phpwiki-special replacement list (persistent replacements)
64 class WikiPlugin_SpellCheck
68 return _("Spell Checker");
70 function getDescription () {
71 return _("Check the spelling of a page and make suggestions");
73 function managesValidators() {
76 function getDefaultArguments() {
77 return array('pagename' => '[]', // button or preview highlight?
81 function pspell_check ($text, $lang=false) {
83 if ($lang) $lang = $GLOBALS['LANG'];
84 $words = preg_split('/[\W]+?/', $text);
86 $misspelled = $return = array();
87 $pspell_config = pspell_config_create($lang, "", "", $charset,
88 PSPELL_NORMAL|PSPELL_RUN_TOGETHER);
89 //pspell_config_runtogether($pspell_config, true);
91 pspell_config_personal($pspell_config, PSPELL_PWL);
93 pspell_config_repl($pspell_config, PSPELL_REPL);
94 $pspell = pspell_new_config($pspell_config);
96 foreach ($words as $value) {
97 // SplitPagename $value
98 if (!pspell_check($pspell, $value)) {
99 $misspelled[] = $value;
102 foreach ($misspelled as $value) {
103 $return[$value] = pspell_suggest($pspell, $value);
108 function pspell_correct ($text, $corrections) {
112 function run($dbi, $argstr, &$request, $basepage) {
113 extract($this->getArgs($argstr, $request));
114 $page = $dbi->getPage($pagename);
115 $current = $page->getCurrentRevision();
116 $source = $current->getPackedContent();
119 return $this->error(fmt("empty source"));
120 if ($basepage == _("SpellCheck"))
121 return $this->error(fmt("Cannot SpellCheck myself"));
122 $lang = $page->get('lang');
123 if (empty($lang)) $lang = $GLOBALS['LANG'];
125 if (!function_exists('pspell_new_config')) {
126 // use the aspell commandline interface
127 include_once 'lib/WikiPluginCached.php';
129 $source = preg_replace("/^/m", "^", $source);
131 $args .= " --data-dir=" . ASPELL_DATA_DIR;
132 // MAYBE TODO: do we have the language dictionary?
133 $args .= " --lang=" . $lang;
134 // use -C or autosplit wikiwords in the text
135 $commandLine = ASPELL_EXE . " -a -C $args ";
136 $cache = new WikiPluginCached;
137 $code = $cache->filterThroughCmd($source, $commandLine);
139 return $this->error(fmt("Couldn't start commandline '%s'",$commandLine));
141 foreach (preg_split("/\n/", $code) as $line) {
142 if (preg_match("/^& (\w+) \d+ \d+: (.+)$/", $line, $m)) {
143 $sugg[$m[1]] = preg_split("/, /", $m[2]);
146 /*$pre = HTML::pre(HTML::raw($code));
147 $html->pushContent($pre);*/
149 $sugg = pspell_check($source, $lang);
151 //$html->pushContent(HTML::hr(),HTML::h1(_("Spellcheck")));
152 $page = $request->getPage();
154 $revision = $page->getRevision($version);
156 NoSuchRevision($request, $page, $version);
159 $revision = $page->getCurrentRevision();
161 $GLOBALS['request']->setArg('suggestions', $sugg);
162 include_once 'lib/BlockParser.php';
163 $ori_html = TransformText($revision, $revision->get('markup'), $page);
164 $GLOBALS['request']->setArg('suggestions', false);
166 $html->pushContent($ori_html, HTML::hr(), HTML::h1(_("SpellCheck result")));
169 foreach ($sugg as $word => $suggs) {
170 $w = HTML::span(array('class' => 'spell-wrong'), $word);
171 // TODO: optional replace-link. jscript or request button with word replace.
173 foreach ($suggs as $s) {
174 $r->pushContent(HTML::a(array('class' => 'spell-sugg',
175 'href' => "javascript:do_replace('$word','$s')"),
178 $list->pushContent(HTML::li($w, _(": "), $r));
180 $html->pushContent($list);
189 // c-hanging-comment-ender-p: nil
190 // indent-tabs-mode: nil