dokuwiki-latex-plugin – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 <?php
2 /**
3 * Admin for LaTeX plugin.
4 *
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Mark Lundeberg <nanite@gmail.com>
7 */
8  
9 if(!defined('DOKU_INC')) die();
10 if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11 require_once(DOKU_PLUGIN.'admin.php');
12  
13 require_once(dirname(__FILE__).'/latexinc.php');
14  
15 /**
16 * All DokuWiki plugins to extend the admin function
17 * need to inherit from this class
18 */
19 class admin_plugin_latex extends DokuWiki_Admin_Plugin {
20 var $output;
21 /**
22 * return some info
23 */
24 function getInfo(){
25 $a = '';
26 if(method_exists(DokuWiki_Admin_Plugin,"getInfo")) {
27 $a = parent::getInfo(); /// this will grab the data from the plugin.info.txt
28 $a['name'] = 'LaTeX plugin administration';
29 return $a;
30 } else
31 // Otherwise return some hardcoded data for old dokuwikis
32 return array(
33 'author' => 'Alexander Kraus, Michael Boyle, and Mark Lundeberg)',
34 'email' => '.',
35 'date' => '???',
36 'name' => 'LaTeX plugin',
37 'desc' => 'LaTeX rendering plugin; requires LaTeX, dvips, ImageMagick.',
38 'url' => 'http://www.dokuwiki.org/plugin:latex'
39 );
40 }
41  
42 /**
43 * return sort order for position in admin menu
44 */
45 function getMenuSort() {
46 return 999;
47 }
48  
49 // Purgers.
50 function vio_atime($fname) {
51 if(time() - fileatime($fname) - $this->_timelimit > 0)
52 {
53 unlink($fname);
54 return $this->_timelimit;
55 }
56 return false;
57 }
58 function vio_mtime($fname) {
59 if(time() - filemtime($fname) - $this->_timelimit > 0)
60 {
61 unlink($fname);
62 return true;
63 }
64 return false;
65 }
66 function vio_all($fname) {
67 unlink($fname);
68 return true;
69 }
70  
71  
72 // purge all files older than $timelimit (in seconds)
73 // $mode =
74 // atime: age based on fileatime().
75 // mtime: age based on filemtime().
76 // all: delete all cached files.
77 function latexpurge($mode, $timelimit)
78 {
79 global $conf, $config_cascade;
80 $meddir = $conf['mediadir'] . '/' . strtr($this->getConf('latex_namespace'),':','/');
81 $images = glob($meddir.'/img*');
82 $this->_timelimit = $timelimit;
83 switch($mode) {
84 case 'atime':
85 $vio = array_map(array($this,'vio_atime'),$images);
86 break;
87 case 'mtime':
88 $vio = array_map(array($this,'vio_mtime'),$images);
89 break;
90 case 'all':
91 $vio = array_map(array($this,'vio_all'),$images);
92 break;
93 default:
94 return false;
95 }
96 return array_combine($images,$vio);
97 }
98  
99 /**
100 * handle user request
101 */
102 function handle() {
103 global $conf, $config_cascade;
104 $this->output = "";
105 if(isset($_POST['latexpurge']))
106 {
107 $mode = $_POST['purgemode'];
108 $days = $_POST['purgedays'];
109 if(is_numeric($days) && $days == 0)
110 $mode = 'all';
111 if($mode == 'all') {
112 // If the admin wants to delete all of the images, probably it's good to print this reminder
113 // since they are likely doing it after changing the colour or something.
114 // (I don't know how many hours I spent trying to fix LaTeX heisenbugs that were just cached... grr.)
115 $this->output .= '<div class="info">'.$this->getLang('refresh_note').'</div>';
116 }
117 $numdeleted = 0;
118 $numkept = 0;
119 $this->output .= "<pre>Purge result ([x] = deleted):\n";
120 if($mode == 'all' || (is_numeric($days) && $days >= 0)) {
121 $res = $this->latexpurge($mode, $days*86400);
122 foreach($res as $img => $vio){
123 if($vio) {
124 $this->output .= '[x] '.$img . "\n";
125 $numdeleted += 1;
126 } else {
127 // $this->output .= '[ ] '.$img . "\n";
128 $numkept += 1;
129 }
130 }
131 } else {
132 $this->output = "<div class=\"error\">Purger: Bad form inputs. No action taken.</div>".$this->output;
133 }
134 $this->output .= "Totals: $numdeleted deleted, $numkept kept (kept files not shown).\n";
135 if ($numdeleted > 0) {
136 touch($config_cascade['main']['local']);
137 }
138 $this->output .= "</pre>";
139 }
140 }
141  
142  
143 /**
144 * output appropriate html
145 */
146 function html() {
147 global $ID,$INFO;
148 ptln('<p>'.$this->output.'</p>');
149 ptln('<h1>LaTeX plugin administrator tasks</h1>');
150 ptln('<h2>'.$this->getLang('legend_purge').'</h2>');
151 ptln('<div class="level2">');
152  
153 ////////////// PURGE FORM
154 ptln('<form action="'.wl($INFO['id']).'?do=admin&page='.$this->getPluginName().'" method="post">');
155 ptln('<table class="inline"><tr>');
156 ptln('<td rowspan="2"><input type="submit" class="button" name="latexpurge" value="'.$this->getLang('btn_purge').'" /></td>');
157 ptln('<TD>');
158 $labtimes = $this->getLang('label_times');
159 ptln('(<LABEL><INPUT type="radio" name="purgemode" value="atime" checked />'.$labtimes['atime'].'</LABEL>');
160 ptln(' | <LABEL><INPUT type="radio" name="purgemode" value="mtime" />'.$labtimes['mtime'].'</LABEL>)');
161 echo $this->getLang('label_olderthan');
162 echo '<input type="text" name="purgedays" size="3" value="30">';
163 echo $this->getLang('label_days');
164 ptln('</TD><TR><TD>');
165 echo '<LABEL><INPUT type="radio" name="purgemode" value="all" />'.$this->getLang('label_all').'</LABEL>';
166 ptln('</TD></TR></TABLE>');
167 ptln('</form>');
168  
169 ptln('</div>');
170  
171 /////////////// DIAGNOSER
172 ptln('<h2>LaTeX troubleshooter</h2>');
173 ptln('<div class="level2">');
174 ptln('<form action="'.wl($INFO['id']).'" method="get">');
175 ptln(' <input type="hidden" name="do" value="admin" />');
176 ptln(' <input type="hidden" name="page" value="'.$this->getPluginName().'" />');
177 ptln('Push this button to diagnose your LaTeX/ImageMagick installation: <input type="submit" class="button" name="dotest" value="Test" /><br/>');
178 ptln('<input type="checkbox" name="keep_tmp">Check this button to keep the temporary files used during compilation.</input><br/>');
179 ptln('The following latex code will be inserted into the template and compiled:');
180 ptln('<br />');
181 if(isset($_REQUEST['testformula']))
182 $testformula = $_REQUEST['testformula'];
183 else
184 $testformula = '$$\underbrace{{\it f}({\rm DokuWiki}) = \overbrace{[a+b=c]}^\textrm{\LaTeX}}_{Success!}$$';
185 ptln(' <textarea cols=70 rows=6 type="text" name="testformula">'.htmlspecialchars($testformula).'</textarea>');
186 ptln('</form>');
187 ptln('</div>');
188 if($_REQUEST['dotest']) {
189 ptln('<h3>Versions</h3>');
190 ptln('<div class="level3">');
191 ptln('This is a test of the acessibility of your programs and their versions.');
192 ptln('<table class="inline">');
193 ptln('<tr><th>command</th><th>output</th></tr>');
194 foreach(array($this->getConf("latex_path"),$this->getConf("dvips_path"),
195 $this->getConf("convert_path"),$this->getConf("identify_path")) as $path) {
196 ptln('<tr><td><pre>');
197 $cmd = $path." --version 2>&1";
198 echo htmlspecialchars($cmd);
199 ptln('</pre></td><td>');
200 unset($execout);
201 exec($cmd,$execout,$statuscode);
202 if($statuscode == 0)
203 echo '<pre>';
204 else
205 echo '<pre style="background-color:#FCC;">'; //pink for error status
206 echo htmlspecialchars(implode(PHP_EOL,$execout));
207 ptln('</pre></td></tr>');
208 }
209 ptln('</table>');
210 ptln('</div>');
211  
212 ptln('<h3>Test run</h3>');
213 $plug = new syntax_plugin_latex_common();
214  
215 /// Directory sanity checks
216 if(is_writable($plug->_latex->getPicturePath()) && is_dir($plug->_latex->getPicturePath()))
217 ptln('<div class="success">Media directory is writable: <code>'.$plug->_latex->getPicturePath().'</code></div>');
218 else
219 ptln('<div class="error">Media directory not writable or nonexistant! <code>'.$plug->_latex->getPicturePath().'</code>
220 <br />Recommendation: This media namespace must be writable on the file system.</div>');
221 if(is_writable($plug->_latex->_tmp_dir) && is_dir($plug->_latex->_tmp_dir))
222 ptln('<div class="success">Temporary directory is writable: <code>'.$plug->_latex->_tmp_dir.'</code></div>');
223 else
224 ptln('<div class="error">Temporary directory not writable or nonexistant! <code>'.$plug->_latex->_tmp_dir.'</code>
225 <br />Recommendation: This media namespace must be writable on the file system.</div>');
226  
227 // simulate a call to the syntax plugin; force render, keep temp files.
228 $md5 = md5($testformula);
229 $outname = $plug->_latex->getPicturePath()."/img".$md5.'.'.$plug->_latex->_image_format;
230 if(file_exists($outname)) {
231 if(unlink($outname))
232 ptln('<div class="info">Removed cache file for test: <code>'.$outname.'</code><br/>
233 <b>WARNING: You may need to refresh your browser\'s cache to see changes in the resulting image.</b></div>');
234 else
235 ptln('<div class="error">Could not remove cached file for test! <code>'.$outname.'</code><br />
236 the following tests will not work (renderer will just reuse the cached file)</div>');
237 }
238 ptln('<div class="info">Attempting to render to target <code>'.$outname.'</code></div>');
239 $plug->_latex->_keep_tmp = true;
240 $plug->_latex->_cmdoutput = ''; // activate command log.
241 $data = array($testformula,DOKU_LEXER_UNMATCHED,'class'=>"latex_inline", 'title'=>"Math", NULL);
242 $this->doc = '';
243 $xhtml = new Doku_Renderer_xhtml();
244 $plug->render('xhtml', $xhtml, $data);
245 $tmpw = $this->getConf('latex_namespace').':tmp:'.$plug->_latex->_tmp_filename;
246 $tmpf = $plug->_latex->_tmp_dir."/".$plug->_latex->_tmp_filename;
247 $tmpext = array('tex','log','aux','dvi','ps',$plug->_latex->_image_format);
248 foreach($tmpext as $ext) {
249 $fname = $tmpf.'.'.$ext;
250 if(is_file($fname)) {
251 if(isset($_REQUEST['keep_tmp'])) {
252 $rendstr = $plug->render('xhtml', $xhtml, '{{'.$tmpw.'.'.$ext.'?linkonly&nocache|'.$fname.'}}');
253 $rendstr = preg_replace('/<\\/?p>/','',$rendstr);
254 } else
255 $rendstr = $fname;
256 ptln('<div class="success">File created: <code>'.$rendstr.'</code></div>');
257 } else
258 ptln('<div class="error">File missing! <code>'.$fname.'</code></div>');
259 }
260 if(! isset($_REQUEST['keep_tmp']))
261 ptln('<div class="info">These files <code>'.$tmpf.'.*</code> will be deleted at the end of this script.</div>');
262 if(is_file($outname))
263 ptln('<div class="success">Successfully moved to media: <code>'.$outname.'</code></div>');
264 else
265 ptln('<div class="error">File missing from media! <code>'.$outname.'</code></div>');
266  
267 ptln('<div class="level3">');
268 ptln('<table class="inline"><tr><th>Input LaTeX file</th><th>Final result</th></tr>');
269 ptln('<tr><td><pre>');
270 if(is_readable($tmpf.'.tex') && is_file($tmpf.'.tex'))
271 echo htmlspecialchars(file_get_contents($tmpf.'.tex'));
272 else
273 echo 'MISSING';
274 ptln('</pre></td><td>');
275 // ptln(htmlspecialchars($plug->_url));
276 // ptln('<br /><br />');
277 ptln('<center>');
278 ptln($this->doc);
279 ptln('</center></td></tr>');
280 ptln('</table>');
281  
282 ptln('Command log:');
283 echo '<pre>';
284 echo $plug->_latex->_cmdoutput;
285 echo '</pre>';
286  
287 ptln('Contents of '.$tmpf.'.log:');
288 echo '<pre>';
289 echo htmlspecialchars(file_get_contents($tmpf.'.log'));
290 echo '</pre>';
291  
292 if(! isset($_REQUEST['keep_tmp']))
293 $plug->_latex->cleanTemporaryDirectory();
294 ptln('</div>');
295 }
296 }
297 }