/
Spellcheck.controller.php
178 lines (152 loc) · 4.77 KB
/
Spellcheck.controller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?php
/**
* Just show the spellchecker.
*
* @name ElkArte Forum
* @copyright ElkArte Forum contributors
* @license BSD http://opensource.org/licenses/BSD-3-Clause
*
* This file contains code covered by:
* copyright: 2011 Simple Machines (http://www.simplemachines.org)
* license: BSD, See included LICENSE.TXT for terms and conditions.
*
* @version 1.1.7
*
*/
/**
* Spellcheck_Controller Class
*
* Handles the initialization pspell and spellchecker processing
*/
class Spellcheck_Controller extends Action_Controller
{
/**
* Known words that pspell will not know
*
* @var array
*/
public $known_words = array('elkarte', 'php', 'mysql', 'www', 'gif', 'jpeg', 'png', 'http');
/**
* The object that holds our initialized pspell
*
* @var object
*/
public $pspell_link;
/**
* The template layers object
*
* @var null|object
*/
protected $_template_layers = null;
/**
* List of words that will be spell checked, word|offset_begin|offset_end
* @var string[]
*/
private $_alphas;
/**
* Spell checks the post for typos ;).
*
* What it does:
*
* - It uses the pspell library, which MUST be installed.
* - It has problems with internationalization.
* - It is accessed via ?action=spellcheck.
* - Triggers the prepare_spellcheck event
*/
public function action_index()
{
global $txt, $context;
// A list of "words" we know about but pspell doesn't.
$this->_events->trigger('prepare_spellcheck', array('$this->known_words' => &$this->known_words));
loadLanguage('Post');
loadTemplate('Post');
// Okay, this looks funny, but it actually fixes a weird bug.
ob_start();
$old = error_reporting(0);
// Next, the dictionary in question may not exist. So, we try it... but...
$this->pspell_link = pspell_new($txt['lang_locale'], $txt['lang_spelling'], null, 'utf-8', PSPELL_FAST);
if (!$this->pspell_link)
{
$this->pspell_link = pspell_new($txt['lang_dictionary'], $txt['lang_spelling'], null, 'utf-8', PSPELL_FAST);
}
// Most people don't have anything but English installed... So we use English as a last resort.
if (!$this->pspell_link)
{
$this->pspell_link = pspell_new('en');
}
// Reset error reporting to what it was
error_reporting($old);
@ob_end_clean();
// Nothing to check or nothing to check with
if (!isset($this->_req->post->spellstring) || !$this->pspell_link)
{
die ('pspell initializing failure');
}
// Get all the words (Javascript already separated them).
$this->_alphas = explode("\n", strtr($this->_req->post->spellstring, array("\r" => '')));
// Construct a bit of Javascript code.
$context['spell_js'] = '
var txt = {"done": "' . $txt['spellcheck_done'] . '"},
mispstr = ' . ($this->_req->post->fulleditor === 'true' ? 'window.opener.spellCheckGetText(spell_fieldname)' : 'window.opener.document.forms[spell_formname][spell_fieldname].value') . ',
misps = ' . $this->_build_misps_array() . '
);';
// And instruct the template system to just show the spellcheck sub template.
$this->_template_layers = Template_Layers::instance();
$this->_template_layers->removeAll();
$context['sub_template'] = 'spellcheck';
}
/**
* Builds the mis spelled words array for use in JS
*
* What it does:
*
* - Examines all words passed to it, checking spelling of each
* - Incorrect ones are supplied an array of possible substitutions
*
* @return string
*/
protected function _build_misps_array()
{
$array = 'Array(';
$found_words = false;
foreach ($this->_alphas as $alpha)
{
// Words are sent like 'word|offset_begin|offset_end'.
$check_word = explode('|', $alpha);
// If the word is a known word, or spelled right...
if (in_array(Util::strtolower($check_word[0]), $this->known_words) || pspell_check($this->pspell_link, $check_word[0]) || !isset($check_word[2]))
{
continue;
}
// Find the word, and move up the "last occurrence" to here.
$found_words = true;
// Add on the javascript for this misspelling.
$array .= '
new misp("' . strtr($check_word[0], array('\\' => '\\\\', '"' => '\\"', '<' => '', '>' => '')) . '", ' . (int) $check_word[1] . ', ' . (int) $check_word[2] . ', [';
// If there are suggestions, add them in...
$suggestions = pspell_suggest($this->pspell_link, $check_word[0]);
if (!empty($suggestions))
{
// But first check they aren't going to be censored - no naughty words!
foreach ($suggestions as $k => $word)
{
if ($suggestions[$k] != censor($word))
{
unset($suggestions[$k]);
}
}
if (!empty($suggestions))
{
$array .= '"' . implode('", "', $suggestions) . '"';
}
}
$array .= ']),';
}
// If words were found, take off the last comma.
if ($found_words)
{
$array = substr($array, 0, -1);
}
return $array;
}
}