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
67 function getDescription()
69 return _("Check the spelling of a page and make suggestions.");
72 function managesValidators()
77 function getDefaultArguments()
79 return array('pagename' => '[]', // button or preview highlight?
83 function pspell_check($text, $lang = false)
85 if ($lang) $lang = $GLOBALS['LANG'];
86 $words = preg_split('/[\W]+?/', $text);
88 $misspelled = $return = array();
89 $pspell_config = pspell_config_create($lang, "", "", 'UTF-8',
90 PSPELL_NORMAL | PSPELL_RUN_TOGETHER);
91 //pspell_config_runtogether($pspell_config, true);
93 pspell_config_personal($pspell_config, PSPELL_PWL);
95 pspell_config_repl($pspell_config, PSPELL_REPL);
96 $pspell = pspell_new_config($pspell_config);
98 foreach ($words as $value) {
99 // SplitPagename $value
100 if (!pspell_check($pspell, $value)) {
101 $misspelled[] = $value;
104 foreach ($misspelled as $value) {
105 $return[$value] = pspell_suggest($pspell, $value);
110 function pspell_correct($text, $corrections)
115 function run($dbi, $argstr, &$request, $basepage)
117 extract($this->getArgs($argstr, $request));
118 $page = $dbi->getPage($pagename);
119 $current = $page->getCurrentRevision();
120 $source = $current->getPackedContent();
123 return $this->error(fmt("empty source"));
124 if ($basepage == _("SpellCheck"))
125 return $this->error(fmt("Cannot SpellCheck myself"));
126 $lang = $page->get('lang');
127 if (empty($lang)) $lang = $GLOBALS['LANG'];
129 if (!function_exists('pspell_new_config')) {
130 // use the aspell commandline interface
131 include_once 'lib/WikiPluginCached.php';
133 $source = preg_replace("/^/m", "^", $source);
135 $args .= " --data-dir=" . ASPELL_DATA_DIR;
136 // MAYBE TODO: do we have the language dictionary?
137 $args .= " --lang=" . $lang;
138 // use -C or autosplit wikiwords in the text
139 $commandLine = ASPELL_EXE . " -a -C $args ";
140 $cache = new WikiPluginCached;
141 $code = $cache->filterThroughCmd($source, $commandLine);
143 return $this->error(fmt("Couldn't start commandline ā%sā", $commandLine));
145 foreach (preg_split("/\n/", $code) as $line) {
146 if (preg_match("/^& (\w+) \d+ \d+: (.+)$/", $line, $m)) {
147 $sugg[$m[1]] = preg_split("/, /", $m[2]);
150 /*$pre = HTML::pre(HTML::raw($code));
151 $html->pushContent($pre);*/
153 $sugg = pspell_check($source, $lang);
155 //$html->pushContent(HTML::hr(),HTML::h1(_("Spellcheck")));
156 $page = $request->getPage();
158 $revision = $page->getRevision($version);
160 NoSuchRevision($request, $page, $version);
162 $revision = $page->getCurrentRevision();
164 $GLOBALS['request']->setArg('suggestions', $sugg);
165 include_once 'lib/BlockParser.php';
166 $ori_html = TransformText($revision, $page);
167 $GLOBALS['request']->setArg('suggestions', false);
169 $html->pushContent($ori_html, HTML::hr(), HTML::h1(_("SpellCheck result")));
172 foreach ($sugg as $word => $suggs) {
173 $w = HTML::span(array('class' => 'spell-wrong'), $word);
174 // TODO: optional replace-link. jscript or request button with word replace.
176 foreach ($suggs as $s) {
177 $r->pushContent(HTML::a(array('class' => 'spell-sugg',
178 'href' => "javascript:do_replace('$word','$s')"),
181 $list->pushContent(HTML::li($w, _(": "), $r));
183 $html->pushContent($list);
192 // c-hanging-comment-ender-p: nil
193 // indent-tabs-mode: nil