1 |
efrain |
1 |
<?php
|
|
|
2 |
// This function fetches math. images from the data directory
|
|
|
3 |
// If not, it obtains the corresponding TeX expression from the cache_tex db table
|
|
|
4 |
// and uses mimeTeX to create the image file
|
|
|
5 |
|
|
|
6 |
require_once("../../config.php");
|
|
|
7 |
|
|
|
8 |
if (!filter_is_enabled('algebra')) {
|
|
|
9 |
throw new \moodle_exception('filternotenabled');
|
|
|
10 |
}
|
|
|
11 |
|
|
|
12 |
require_once($CFG->libdir.'/filelib.php');
|
|
|
13 |
require_once($CFG->dirroot.'/filter/tex/lib.php');
|
|
|
14 |
|
|
|
15 |
$action = optional_param('action', '', PARAM_ALPHANUM);
|
|
|
16 |
$algebra = optional_param('algebra', '', PARAM_RAW);
|
|
|
17 |
|
|
|
18 |
require_login();
|
|
|
19 |
require_capability('moodle/site:config', context_system::instance());
|
|
|
20 |
if ($action || $algebra) {
|
|
|
21 |
require_sesskey();
|
|
|
22 |
}
|
|
|
23 |
|
|
|
24 |
if ($algebra && $action) {
|
|
|
25 |
$md5 = md5($algebra);
|
|
|
26 |
if ($action == 'ShowDB' || $action == 'DeleteDB') {
|
|
|
27 |
$texcache = $DB->get_record("cache_filters", array("filter"=>"algebra", "md5key"=>$md5));
|
|
|
28 |
}
|
|
|
29 |
if ($action == 'ShowDB') {
|
|
|
30 |
if ($texcache) {
|
|
|
31 |
$output = "DB cache_filters entry for $algebra\n";
|
|
|
32 |
$output .= "id = $texcache->id\n";
|
|
|
33 |
$output .= "filter = $texcache->filter\n";
|
|
|
34 |
$output .= "version = $texcache->version\n";
|
|
|
35 |
$output .= "md5key = $texcache->md5key\n";
|
|
|
36 |
$output .= "rawtext = $texcache->rawtext\n";
|
|
|
37 |
$output .= "timemodified = $texcache->timemodified\n";
|
|
|
38 |
} else {
|
|
|
39 |
$output = "DB cache_filters entry for $algebra not found\n";
|
|
|
40 |
}
|
|
|
41 |
}
|
|
|
42 |
if ($action == 'DeleteDB') {
|
|
|
43 |
if ($texcache) {
|
|
|
44 |
$output = "Deleting DB cache_filters entry for $algebra\n";
|
|
|
45 |
$result = $DB->delete_records("cache_filters", array("id"=>$texcache->id));
|
|
|
46 |
if ($result) {
|
|
|
47 |
$result = 1;
|
|
|
48 |
} else {
|
|
|
49 |
$result = 0;
|
|
|
50 |
}
|
|
|
51 |
$output .= "Number of records deleted = $result\n";
|
|
|
52 |
} else {
|
|
|
53 |
$output = "Could not delete DB cache_filters entry for $algebra\nbecause it could not be found.\n";
|
|
|
54 |
}
|
|
|
55 |
}
|
|
|
56 |
if ($action == 'TeXStage1') {
|
|
|
57 |
$output = algebra2tex($algebra);
|
|
|
58 |
}
|
|
|
59 |
if ($action == 'TexStage2') {
|
|
|
60 |
$output = algebra2tex($algebra);
|
|
|
61 |
$output = refineTeX($output);
|
|
|
62 |
}
|
|
|
63 |
if ($action == 'ShowImage'|| $action == 'SlashArguments') {
|
|
|
64 |
$output = algebra2tex($algebra);
|
|
|
65 |
$output = refineTeX($output);
|
|
|
66 |
if ($action == 'ShowImage') {
|
|
|
67 |
tex2image($output, $md5);
|
|
|
68 |
} else {
|
|
|
69 |
slasharguments($output, $md5);
|
|
|
70 |
}
|
|
|
71 |
} else {
|
|
|
72 |
outputText($output);
|
|
|
73 |
}
|
|
|
74 |
exit;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
function algebra2tex($algebra) {
|
|
|
78 |
global $CFG;
|
|
|
79 |
$algebra = str_replace('<','<',$algebra);
|
|
|
80 |
$algebra = str_replace('>','>',$algebra);
|
|
|
81 |
$algebra = str_replace('<>','#',$algebra);
|
|
|
82 |
$algebra = str_replace('<=','%',$algebra);
|
|
|
83 |
$algebra = str_replace('>=','!',$algebra);
|
|
|
84 |
$algebra = preg_replace('/([=><%!#] *)-/',"\$1 zeroplace -",$algebra);
|
|
|
85 |
$algebra = str_replace('delta','zdelta',$algebra);
|
|
|
86 |
$algebra = str_replace('beta','bita',$algebra);
|
|
|
87 |
$algebra = str_replace('theta','thita',$algebra);
|
|
|
88 |
$algebra = str_replace('zeta','zita',$algebra);
|
|
|
89 |
$algebra = str_replace('eta','xeta',$algebra);
|
|
|
90 |
$algebra = str_replace('epsilon','zepslon',$algebra);
|
|
|
91 |
$algebra = str_replace('upsilon','zupslon',$algebra);
|
|
|
92 |
$algebra = preg_replace('!\r\n?!',' ',$algebra);
|
|
|
93 |
$algebra = escapeshellarg($algebra);
|
|
|
94 |
|
|
|
95 |
if ( (PHP_OS == "WINNT") || (PHP_OS == "WIN32") || (PHP_OS == "Windows") ) {
|
|
|
96 |
$cmd = "cd $CFG->dirroot\\filter\\algebra & algebra2tex.pl x/2";
|
|
|
97 |
$test = `$cmd`;
|
|
|
98 |
if ($test != '\frac{x}{2}') {
|
|
|
99 |
echo "There is a problem with either Perl or the script algebra2tex.pl<br/>";
|
|
|
100 |
$ecmd = $cmd . " 2>&1";
|
|
|
101 |
echo `$ecmd` . "<br/>\n";
|
|
|
102 |
echo "The shell command<br/>$cmd<br/>returned status = $status<br/>\n";
|
|
|
103 |
$commandpath = "$CFG->dirroot\\filter\\algebra\\algebra2tex.pl";
|
|
|
104 |
if (file_exists($commandpath)) {
|
|
|
105 |
echo "The file permissions of algebra2tex.pl are: " . decoct(fileperms($commandpath)) . "<br/>";
|
|
|
106 |
}
|
|
|
107 |
die;
|
|
|
108 |
}
|
|
|
109 |
$cmd = "cd $CFG->dirroot\\filter\\algebra & algebra2tex.pl $algebra";
|
|
|
110 |
} else {
|
|
|
111 |
$cmd = "cd $CFG->dirroot/filter/algebra; ./algebra2tex.pl x/2";
|
|
|
112 |
$test = `$cmd`;
|
|
|
113 |
if ($test != '\frac{x}{2}') {
|
|
|
114 |
echo "There is a problem with either Perl or the script algebra2tex.pl<br/>";
|
|
|
115 |
$ecmd = $cmd . " 2>&1";
|
|
|
116 |
echo `$ecmd` . "<br/>\n";
|
|
|
117 |
echo "The shell command<br/>$cmd<br/>returned status = $status<br/>\n";
|
|
|
118 |
$commandpath = "$CFG->dirroot/filter/algebra/algebra2tex.pl";
|
|
|
119 |
if (file_exists($commandpath)) {
|
|
|
120 |
echo "The file permissions of algebra2tex.pl are: " . decoct(fileperms($commandpath)) . "<br/>";
|
|
|
121 |
}
|
|
|
122 |
die;
|
|
|
123 |
}
|
|
|
124 |
$cmd = "cd $CFG->dirroot/filter/algebra; ./algebra2tex.pl $algebra";
|
|
|
125 |
}
|
|
|
126 |
$texexp = `$cmd`;
|
|
|
127 |
return $texexp;
|
|
|
128 |
}
|
|
|
129 |
|
|
|
130 |
function refineTeX($texexp) {
|
|
|
131 |
$texexp = str_replace('zeroplace','',$texexp);
|
|
|
132 |
$texexp = str_replace('#','\not= ',$texexp);
|
|
|
133 |
$texexp = str_replace('%','\leq ',$texexp);
|
|
|
134 |
$texexp = str_replace('!','\geq ',$texexp);
|
|
|
135 |
$texexp = str_replace('\left{','{',$texexp);
|
|
|
136 |
$texexp = str_replace('\right}','}',$texexp);
|
|
|
137 |
$texexp = str_replace('\fun',' ',$texexp);
|
|
|
138 |
$texexp = str_replace('infty','\infty',$texexp);
|
|
|
139 |
$texexp = str_replace('alpha','\alpha',$texexp);
|
|
|
140 |
$texexp = str_replace('gamma','\gamma',$texexp);
|
|
|
141 |
$texexp = str_replace('iota','\iota',$texexp);
|
|
|
142 |
$texexp = str_replace('kappa','\kappa',$texexp);
|
|
|
143 |
$texexp = str_replace('lambda','\lambda',$texexp);
|
|
|
144 |
$texexp = str_replace('mu','\mu',$texexp);
|
|
|
145 |
$texexp = str_replace('nu','\nu',$texexp);
|
|
|
146 |
$texexp = str_replace('xi','\xi',$texexp);
|
|
|
147 |
$texexp = str_replace('rho','\rho',$texexp);
|
|
|
148 |
$texexp = str_replace('sigma','\sigma',$texexp);
|
|
|
149 |
$texexp = str_replace('tau','\tau',$texexp);
|
|
|
150 |
$texexp = str_replace('phi','\phi',$texexp);
|
|
|
151 |
$texexp = str_replace('chi','\chi',$texexp);
|
|
|
152 |
$texexp = str_replace('psi','\psi',$texexp);
|
|
|
153 |
$texexp = str_replace('omega','\omega',$texexp);
|
|
|
154 |
$texexp = str_replace('zdelta','\delta',$texexp);
|
|
|
155 |
$texexp = str_replace('bita','\beta',$texexp);
|
|
|
156 |
$texexp = str_replace('thita','\theta',$texexp);
|
|
|
157 |
$texexp = str_replace('zita','\zeta',$texexp);
|
|
|
158 |
$texexp = str_replace('xeta','\eta',$texexp);
|
|
|
159 |
$texexp = str_replace('zepslon','\epsilon',$texexp);
|
|
|
160 |
$texexp = str_replace('zupslon','\upsilon',$texexp);
|
|
|
161 |
$texexp = str_replace('\mbox{logten}','\mbox{log}_{10}',$texexp);
|
|
|
162 |
$texexp = str_replace('\mbox{acos}','\mbox{cos}^{-1}',$texexp);
|
|
|
163 |
$texexp = str_replace('\mbox{asin}','\mbox{sin}^{-1}',$texexp);
|
|
|
164 |
$texexp = str_replace('\mbox{atan}','\mbox{tan}^{-1}',$texexp);
|
|
|
165 |
$texexp = str_replace('\mbox{asec}','\mbox{sec}^{-1}',$texexp);
|
|
|
166 |
$texexp = str_replace('\mbox{acsc}','\mbox{csc}^{-1}',$texexp);
|
|
|
167 |
$texexp = str_replace('\mbox{acot}','\mbox{cot}^{-1}',$texexp);
|
|
|
168 |
$texexp = str_replace('\mbox{acosh}','\mbox{cosh}^{-1}',$texexp);
|
|
|
169 |
$texexp = str_replace('\mbox{asinh}','\mbox{sinh}^{-1}',$texexp);
|
|
|
170 |
$texexp = str_replace('\mbox{atanh}','\mbox{tanh}^{-1}',$texexp);
|
|
|
171 |
$texexp = str_replace('\mbox{asech}','\mbox{sech}^{-1}',$texexp);
|
|
|
172 |
$texexp = str_replace('\mbox{acsch}','\mbox{csch}^{-1}',$texexp);
|
|
|
173 |
$texexp = str_replace('\mbox{acoth}','\mbox{coth}^{-1}',$texexp);
|
|
|
174 |
$texexp = preg_replace('/\\\sqrt{(.+?),(.+?)}/s','\sqrt['. "\$2]{\$1}",$texexp);
|
|
|
175 |
$texexp = preg_replace('/\\\mbox{abs}\\\left\((.+?)\\\right\)/s',"|\$1|",$texexp);
|
|
|
176 |
$texexp = preg_replace('/\\\log\\\left\((.+?),(.+?)\\\right\)/s','\log_{'. "\$2}\\left(\$1\\right)",$texexp);
|
|
|
177 |
$texexp = preg_replace('/(\\\cos|\\\sin|\\\tan|\\\sec|\\\csc|\\\cot)([h]*)\\\left\((.+?),(.+?)\\\right\)/s',"\$1\$2^{". "\$4}\\left(\$3\\right)",$texexp);
|
|
|
178 |
$texexp = preg_replace('/\\\int\\\left\((.+?),(.+?),(.+?)\\\right\)/s','\int_'. "{\$2}^{\$3}\$1 ",$texexp);
|
|
|
179 |
$texexp = preg_replace('/\\\int\\\left\((.+?d[a-z])\\\right\)/s','\int '. "\$1 ",$texexp);
|
|
|
180 |
$texexp = preg_replace('/\\\lim\\\left\((.+?),(.+?),(.+?)\\\right\)/s','\lim_'. "{\$2\\to \$3}\$1 ",$texexp);
|
|
|
181 |
return $texexp;
|
|
|
182 |
}
|
|
|
183 |
|
|
|
184 |
function outputText($texexp) {
|
|
|
185 |
header("Content-type: text/html; charset=utf-8");
|
|
|
186 |
echo "<html><body><pre>\n";
|
|
|
187 |
if ($texexp) {
|
|
|
188 |
$texexp = str_replace('<','<',$texexp);
|
|
|
189 |
$texexp = str_replace('>','>',$texexp);
|
|
|
190 |
$texexp = str_replace('"','"',$texexp);
|
|
|
191 |
echo "$texexp\n\n";
|
|
|
192 |
} else {
|
|
|
193 |
echo "No text output available\n\n";
|
|
|
194 |
}
|
|
|
195 |
echo "</pre></body></html>\n";
|
|
|
196 |
}
|
|
|
197 |
|
|
|
198 |
function tex2image($texexp, $md5, $return=false) {
|
|
|
199 |
global $CFG;
|
|
|
200 |
|
|
|
201 |
if (!$texexp) {
|
|
|
202 |
echo 'No tex expresion specified';
|
|
|
203 |
return;
|
|
|
204 |
}
|
|
|
205 |
|
|
|
206 |
$texexp = '\Large ' . $texexp;
|
|
|
207 |
$image = $md5 . ".gif";
|
|
|
208 |
$filetype = 'image/gif';
|
|
|
209 |
if (!file_exists("$CFG->dataroot/filter/algebra")) {
|
|
|
210 |
make_upload_directory("filter/algebra");
|
|
|
211 |
}
|
|
|
212 |
$pathname = "$CFG->dataroot/filter/algebra/$image";
|
|
|
213 |
if (file_exists($pathname)) {
|
|
|
214 |
unlink($pathname);
|
|
|
215 |
}
|
|
|
216 |
$commandpath = filter_tex_get_executable(true);
|
|
|
217 |
$cmd = filter_tex_get_cmd($pathname, $texexp);
|
|
|
218 |
system($cmd, $status);
|
|
|
219 |
|
|
|
220 |
if ($return) {
|
|
|
221 |
return $image;
|
|
|
222 |
}
|
|
|
223 |
if (file_exists($pathname)) {
|
|
|
224 |
send_file($pathname, $image);
|
|
|
225 |
|
|
|
226 |
} else {
|
|
|
227 |
$ecmd = "$cmd 2>&1";
|
|
|
228 |
echo `$ecmd` . "<br />\n";
|
|
|
229 |
echo "The shell command<br />$cmd<br />returned status = $status<br />\n";
|
|
|
230 |
if ($status == 4) {
|
|
|
231 |
echo "Status corresponds to illegal instruction<br />\n";
|
|
|
232 |
} else if ($status == 11) {
|
|
|
233 |
echo "Status corresponds to bus error<br />\n";
|
|
|
234 |
} else if ($status == 22) {
|
|
|
235 |
echo "Status corresponds to abnormal termination<br />\n";
|
|
|
236 |
}
|
|
|
237 |
if (file_exists($commandpath)) {
|
|
|
238 |
echo "File size of mimetex executable $commandpath is " . filesize($commandpath) . "<br />";
|
|
|
239 |
echo "The file permissions are: " . decoct(fileperms($commandpath)) . "<br />";
|
|
|
240 |
if (function_exists("md5_file")) {
|
|
|
241 |
echo "The md5 checksum of the file is " . md5_file($commandpath) . "<br />";
|
|
|
242 |
} else {
|
|
|
243 |
$handle = fopen($commandpath,"rb");
|
|
|
244 |
$contents = fread($handle,16384);
|
|
|
245 |
fclose($handle);
|
|
|
246 |
echo "The md5 checksum of the first 16384 bytes is " . md5($contents) . "<br />";
|
|
|
247 |
}
|
|
|
248 |
} else {
|
|
|
249 |
echo "mimetex executable $commandpath not found!<br />";
|
|
|
250 |
}
|
|
|
251 |
echo "Image not found!";
|
|
|
252 |
}
|
|
|
253 |
}
|
|
|
254 |
|
|
|
255 |
function slasharguments($texexp, $md5) {
|
|
|
256 |
global $CFG;
|
|
|
257 |
$admin = $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=http';
|
|
|
258 |
$image = tex2image($texexp,$md5,true);
|
|
|
259 |
echo "<p>If the following image displays correctly, set your ";
|
|
|
260 |
echo "<a href=\"$admin\" target=\"_blank\">Administration->Server->HTTP</a> ";
|
|
|
261 |
echo "setting for slasharguments to file.php/1/pic.jpg: ";
|
|
|
262 |
echo "<img src=\"pix.php/$image\" align=\"absmiddle\"></p>\n";
|
|
|
263 |
echo "<p>Otherwise set it to file.php?file=/1/pic.jpg ";
|
|
|
264 |
echo "It should display correctly as ";
|
|
|
265 |
echo "<img src=\"pix.php?file=$image\" align=\"absmiddle\"></p>\n";
|
|
|
266 |
echo "<p>If neither equation image displays correctly, please seek ";
|
|
|
267 |
echo "further help at moodle.org at the ";
|
|
|
268 |
echo "<a href=\"http://moodle.org/mod/forum/view.php?id=752&loginguest=true\" target=\"_blank\">";
|
|
|
269 |
echo "Mathematics Tools Forum</a></p>";
|
|
|
270 |
}
|
|
|
271 |
|
|
|
272 |
?>
|
|
|
273 |
|
|
|
274 |
<html>
|
|
|
275 |
<head><title>Algebra Filter Debugger</title></head>
|
|
|
276 |
<body>
|
|
|
277 |
<p>Please enter an algebraic expression <b>without</b> any surrounding @@ into
|
|
|
278 |
the text box below. (Click <a href="#help">here for help.</a>)
|
|
|
279 |
<form action="algebradebug.php" method="get"
|
|
|
280 |
target="inlineframe">
|
|
|
281 |
<center>
|
|
|
282 |
<label for="algebra" class="accesshide"><?php print_string('algebraicexpression', 'filter_algebra'); ?></label>
|
|
|
283 |
<input type="text" id="algebra" name="algebra" size="50"
|
|
|
284 |
value="sin(z)/(x^2+y^2)" />
|
|
|
285 |
</center>
|
|
|
286 |
<ol>
|
|
|
287 |
<li>First click on this button <button type="submit" name="action" value="ShowDB">Show DB Entry</button>
|
|
|
288 |
to see the cache_filters database entry for this expression.</li>
|
|
|
289 |
<li>If the database entry looks corrupt, click on this button to delete it:
|
|
|
290 |
<button type="submit" name="action" value="DeleteDB">Delete DB Entry</button></li>
|
|
|
291 |
<li>Now click on this button <button type="submit" name="action" value="TeXStage1">First Stage Tex Translation</button>.
|
|
|
292 |
A preliminary translation into TeX will appear in the box below.</li>
|
|
|
293 |
<li>Next click on this button <button type="submit" name="action" value="TexStage2">Second Stage Tex Translation</button>.
|
|
|
294 |
A more refined translation into TeX will appear in the box below.</li>
|
|
|
295 |
<li>Then click on this button <button type="submit" name="action" value="ShowImage">Show Image</button>
|
|
|
296 |
to show a graphic image of the algebraic expression.</li>
|
|
|
297 |
<li>Finally check your slash arguments setting
|
|
|
298 |
<button type="submit" name="action" value="SlashArguments">Check Slash Arguments</button></li>
|
|
|
299 |
</ol>
|
|
|
300 |
<input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />
|
|
|
301 |
</form> <br /> <br />
|
|
|
302 |
<center>
|
|
|
303 |
<iframe name="inlineframe" align="middle" width="80%" height="200">
|
|
|
304 |
<p>Something is wrong...</p>
|
|
|
305 |
</iframe>
|
|
|
306 |
</center> <br />
|
|
|
307 |
<hr />
|
|
|
308 |
<a name="help">
|
|
|
309 |
<h2>Debugging Help</h2>
|
|
|
310 |
</a>
|
|
|
311 |
<p>First here is a brief overview on how the algebra filter works. It
|
|
|
312 |
takes an algebra expression and first translates it into TeX. It first
|
|
|
313 |
looks for the TeX translation in the Moodle database in the table cache_filters
|
|
|
314 |
in the field rawtext. If not found, it passes the algebraic expression to the
|
|
|
315 |
Perl script algebra2tex.pl, which also uses the Perl library AlgParser.pm.
|
|
|
316 |
It then saves the TeX translation in the database for subsequent uses and
|
|
|
317 |
passes the TeX to the mimetex executable to be converted to a gif image.
|
|
|
318 |
Here are a few common things that can go wrong and some suggestions on how
|
|
|
319 |
you might try to fix them.</p>
|
|
|
320 |
<ol>
|
|
|
321 |
<li>Something had gone wrong on a previous occasion when the filter tried to
|
|
|
322 |
translate this expression. Then the database entry for that expression contains
|
|
|
323 |
a bad TeX translation in the rawtext field (usually blank). You can fix this
|
|
|
324 |
by clicking on "Delete DB Entry"</li>
|
|
|
325 |
<li>The First Stage TeX Translation gives a "No text output available"
|
|
|
326 |
message. If your server is running Windows, this may be due to the fact that
|
|
|
327 |
you haven't installed Perl or didn't install it correctly. If your server is
|
|
|
328 |
running some version of Unix (e.g. Linux), then this may be due to your Perl
|
|
|
329 |
binary being installed in a nonstandard location. To fix this edit the first
|
|
|
330 |
line of the algebra2tex.pl script. Another possible problem which may affect
|
|
|
331 |
both Unix and Windows servers is that the web server doesn't have execute permission
|
|
|
332 |
on the algebra2tex.pl script. In that case change permissions accordingly</li>
|
|
|
333 |
<li>The Second Stage TeX Translation produces malformed TeX. This indicates
|
|
|
334 |
a bug in the algebra filter. Post the original algebraic expression and the
|
|
|
335 |
bad TeX translation in the <a href="http://moodle.org/mod/forum/view.php?id=752">
|
|
|
336 |
Mathematics Tools</a> forum in the Using Moodle course on moodle.org.</li>
|
|
|
337 |
<li>The TeX to gif image conversion process does not work. If your server is
|
|
|
338 |
running Unix, a likely cause is that the mimetex binary you are using is
|
|
|
339 |
incompatible with your operating system. You can try compiling it from the
|
|
|
340 |
C sources downloaded from <a href="http://www.forkosh.com/mimetex.zip">
|
|
|
341 |
http://www.forkosh.com/mimetex.zip</a>. Lastly check the execute permissions
|
|
|
342 |
on your mimetex binary, as outlined in item 2 above.</li>
|
|
|
343 |
</ol>
|
|
|
344 |
</body>
|
|
|
345 |
</html>
|