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
69 return _("Spell Checker");
72 function getDescription()
74 return _("Check the spelling of a page and make suggestions.");
77 function managesValidators()
82 function getDefaultArguments()
84 return array('pagename' => '[]', // button or preview highlight?
88 function pspell_check($text, $lang = false)
91 if ($lang) $lang = $GLOBALS['LANG'];
92 $words = preg_split('/[\W]+?/', $text);
94 $misspelled = $return = array();
95 $pspell_config = pspell_config_create($lang, "", "", $charset,
96 PSPELL_NORMAL | PSPELL_RUN_TOGETHER);
97 //pspell_config_runtogether($pspell_config, true);
99 pspell_config_personal($pspell_config, PSPELL_PWL);
101 pspell_config_repl($pspell_config, PSPELL_REPL);
102 $pspell = pspell_new_config($pspell_config);
104 foreach ($words as $value) {
105 // SplitPagename $value
106 if (!pspell_check($pspell, $value)) {
107 $misspelled[] = $value;
110 foreach ($misspelled as $value) {
111 $return[$value] = pspell_suggest($pspell, $value);
116 function pspell_correct($text, $corrections)
121 function run($dbi, $argstr, &$request, $basepage)
123 extract($this->getArgs($argstr, $request));
124 $page = $dbi->getPage($pagename);
125 $current = $page->getCurrentRevision();
126 $source = $current->getPackedContent();
129 return $this->error(fmt("empty source"));
130 if ($basepage == _("SpellCheck"))
131 return $this->error(fmt("Cannot SpellCheck myself"));
132 $lang = $page->get('lang');
133 if (empty($lang)) $lang = $GLOBALS['LANG'];
135 if (!function_exists('pspell_new_config')) {
136 // use the aspell commandline interface
137 include_once 'lib/WikiPluginCached.php';
139 $source = preg_replace("/^/m", "^", $source);
141 $args .= " --data-dir=" . ASPELL_DATA_DIR;
142 // MAYBE TODO: do we have the language dictionary?
143 $args .= " --lang=" . $lang;
144 // use -C or autosplit wikiwords in the text
145 $commandLine = ASPELL_EXE . " -a -C $args ";
146 $cache = new WikiPluginCached;
147 $code = $cache->filterThroughCmd($source, $commandLine);
149 return $this->error(fmt("Couldn't start commandline ā%sā", $commandLine));
151 foreach (preg_split("/\n/", $code) as $line) {
152 if (preg_match("/^& (\w+) \d+ \d+: (.+)$/", $line, $m)) {
153 $sugg[$m[1]] = preg_split("/, /", $m[2]);
156 /*$pre = HTML::pre(HTML::raw($code));
157 $html->pushContent($pre);*/
159 $sugg = pspell_check($source, $lang);
161 //$html->pushContent(HTML::hr(),HTML::h1(_("Spellcheck")));
162 $page = $request->getPage();
164 $revision = $page->getRevision($version);
166 NoSuchRevision($request, $page, $version);
168 $revision = $page->getCurrentRevision();
170 $GLOBALS['request']->setArg('suggestions', $sugg);
171 include_once 'lib/BlockParser.php';
172 $ori_html = TransformText($revision, $revision->get('markup'), $page);
173 $GLOBALS['request']->setArg('suggestions', false);
175 $html->pushContent($ori_html, HTML::hr(), HTML::h1(_("SpellCheck result")));
178 foreach ($sugg as $word => $suggs) {
179 $w = HTML::span(array('class' => 'spell-wrong'), $word);
180 // TODO: optional replace-link. jscript or request button with word replace.
182 foreach ($suggs as $s) {
183 $r->pushContent(HTML::a(array('class' => 'spell-sugg',
184 'href' => "javascript:do_replace('$word','$s')"),
187 $list->pushContent(HTML::li($w, _(": "), $r));
189 $html->pushContent($list);
198 // c-hanging-comment-ender-p: nil
199 // indent-tabs-mode: nil