]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/SpellCheck.php
Remove history
[SourceForge/phpwiki.git] / lib / plugin / SpellCheck.php
1 <?php // -*-php-*-
2 rcs_id('$Id$');
3 /**
4  Copyright 2006,2007 $ThePhpWikiProgrammingTeam
5
6  This file is part of PhpWiki.
7
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.
12
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.
17
18  You should have received a copy of the GNU General Public License
19  along with PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /**
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.
27  *
28  * The pspell extension is better, because it's easier to store corrections.
29  * Enchant looks more promising, because it supports multiple speller backends.
30  *
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
35     or 
36   sed s,^,\^^, $pagename | aspell --lang=$LANG -a -C
37 =>
38   & phpwiki 62 30: pipework, paprika, Popek, Phip, Pike, Viki, pike, ...
39  */
40
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'))
49         if (isWindows())
50             define('ASPELL_DATA_DIR','c:\cygwin\usr\share\aspell');
51         else
52             define('ASPELL_DATA_DIR','/usr/share/aspell');
53     //define('ASPELL_DATA_DIR','/home/groups/p/ph/phpwiki/share/highlight');
54 } else {
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)
62 }
63
64 class WikiPlugin_SpellCheck
65 extends WikiPlugin
66 {
67     function getName () {
68         return _("Spell Checker");
69     }
70     function getDescription () {
71         return _("Check the spelling of a page and make suggestions");
72     }
73     function managesValidators() {
74         return true;
75     }
76     function getVersion() {
77         return preg_replace("/[Revision: $]/", '',
78                             "\$Revision$");
79     }
80     function getDefaultArguments() {
81         return array('pagename' => '[]', // button or preview highlight?
82                      );
83     }
84
85     function pspell_check ($text, $lang=false) {
86         global $charset;
87         if ($lang) $lang = $GLOBALS['LANG'];
88         $words = preg_split('/[\W]+?/', $text);
89
90         $misspelled = $return = array();
91         $pspell_config = pspell_config_create($lang, "", "", $charset, 
92                                               PSPELL_NORMAL|PSPELL_RUN_TOGETHER);
93         //pspell_config_runtogether($pspell_config, true);
94         if (PSPELL_PWL)
95             pspell_config_personal($pspell_config, PSPELL_PWL);
96         if (PSPELL_REPL)
97             pspell_config_repl($pspell_config, PSPELL_REPL);
98         $pspell = pspell_new_config($pspell_config);
99
100         foreach ($words as $value) {
101             // SplitPagename $value
102             if (!pspell_check($pspell, $value)) {
103                 $misspelled[] = $value;
104             }
105         }
106         foreach ($misspelled as $value) {
107             $return[$value] = pspell_suggest($pspell, $value);
108         }
109         return $return;
110     }
111
112     function pspell_correct ($text, $corrections) {
113         ;
114     }
115
116     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();
121
122         if (empty($source))
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'];
128         $html = HTML();
129         if (!function_exists('pspell_new_config')) {
130             // use the aspell commandline interface
131             include_once("lib/WikiPluginCached.php");
132             $args = "";
133             $source = preg_replace("/^/m", "^", $source);
134             if (ASPELL_DATA_DIR)
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);
142             if (empty($code))
143                 return $this->error(fmt("Couldn't start commandline '%s'",$commandLine));
144             $sugg = array();
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]);
148                 }
149             }
150             /*$pre = HTML::pre(HTML::raw($code));
151             $html->pushContent($pre);*/
152         } else {
153             $sugg = pspell_check($source, $lang);
154         }
155         //$html->pushContent(HTML::hr(),HTML::h1(_("Spellcheck")));
156         $page = $request->getPage();
157         if ($version) {
158             $revision = $page->getRevision($version);
159             if (!$revision)
160                 NoSuchRevision($request, $page, $version);
161         }
162         else {
163             $revision = $page->getCurrentRevision();
164         }
165         $GLOBALS['request']->setArg('suggestions', $sugg);
166         include_once("lib/BlockParser.php");
167         $ori_html = TransformText($revision, $revision->get('markup'), $page);
168         $GLOBALS['request']->setArg('suggestions', false);
169
170         $html->pushContent($ori_html, HTML::hr(), HTML::h1(_("SpellCheck result")));
171
172         $list = HTML::ul();
173         foreach ($sugg as $word => $suggs) {
174             $w = HTML::span(array('class' => 'spell-wrong'), $word);
175             // TODO: optional replace-link. jscript or request button with word replace.
176             $r = HTML();
177             foreach ($suggs as $s) {
178                 $r->pushContent(HTML::a(array('class' => 'spell-sugg',
179                                               'href' => "javascript:do_replace('$word','$s')"), 
180                                         $s),", ");
181             }
182             $list->pushContent(HTML::li($w, ": ", $r));
183         }
184         $html->pushContent($list);
185         return $html;
186     }
187 };
188
189 // For emacs users
190 // Local Variables:
191 // mode: php
192 // tab-width: 8
193 // c-basic-offset: 4
194 // c-hanging-comment-ender-p: nil
195 // indent-tabs-mode: nil
196 // End:
197 ?>