]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/Ploticus.php
extended description
[SourceForge/phpwiki.git] / lib / plugin / Ploticus.php
1 <?php // -*-php-*-
2 rcs_id('$Id: Ploticus.php,v 1.2 2004-06-02 19:37:07 rurban Exp $');
3 /**
4  Copyright 2004 $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  * The Ploticus plugin passes all its arguments to the ploticus 
25  * binary and displays the result as PNG, GIF, EPS or SVG.
26  * Ploticus is a free, GPL, non-interactive software package 
27  * for producing plots, charts, and graphics from data.
28  * See http://ploticus.sourceforge.net/doc/welcome.html
29  *
30  * @Author: Reini Urban
31  *
32  * Note: 
33  * - For windows you need either a gd library with GIF support or 
34  *   a ploticus with PNG support. This comes only with the cygwin built.
35  * - We support only images supported by GD so far (PNG most likely). 
36  *   No EPS, PS, SVG or SVGZ support due to limitations in WikiPluginCached.
37  *
38  * Usage:
39 <?plugin Ploticus device=png [ploticus options...]
40    multiline ploticus script ...
41 ?>
42  * or without any script: 
43 <?plugin Ploticus -prefab vbars data=myfile.dat delim=tab y=1 clickmapurl="http://mywiki.url/wiki/?pagename=@2" clickmaplabel="@3" -csmap ?>
44  *
45  * TODO: PloticusSql - create intermediate data from SQL. Similar to SqlResult, just in graphic form.
46  * For example to proeduce nice looking pagehit statistics or ratings statistics.
47  */
48
49 if (isWindows())
50     define('PLOTICUS_EXE','pl.exe');
51 else
52     define('PLOTICUS_EXE','/usr/local/bin/pl');
53
54 require_once "lib/WikiPluginCached.php"; 
55
56 class WikiPlugin_Ploticus
57 extends WikiPluginCached
58 {
59     /**
60      * Sets plugin type to MAP if -csmap (-map or -mapdemo or -csmapdemo not supported)
61      * or HTML if the imagetype is not supported by GD (EPS, SVG, SVGZ) (not yet)
62      * or IMAGE if device = png, gif or jpeg
63      */
64     function getPluginType() {
65         if (!empty($this->_args['-csmap']))
66             return PLUGIN_CACHED_MAP; // not yet tested
67         else    
68             return PLUGIN_CACHED_IMG_INLINE;
69     }
70     function getName () {
71         return _("Ploticus");
72     }
73     function getDescription () {
74         return _("Ploticus image creation");
75     }
76     function managesValidators() {
77         return true;
78     }
79     function getVersion() {
80         return preg_replace("/[Revision: $]/", '',
81                             "\$Revision: 1.2 $");
82     }
83     function getDefaultArguments() {
84         return array(
85                      'device' => 'png', // png,gif,svgz,svg,...
86                      '-csmap' => false,
87                      'alt'    => false,
88                      'help'   => false,
89                      );
90     }
91     function handle_plugin_args_cruft(&$argstr, &$args) {
92         $this->source = $argstr;
93     }
94     /**
95      * Sets the expire time to one day (so the image producing
96      * functions are called seldomly) or to about two minutes
97      * if a help screen is created.
98      */
99     function getExpire($dbi, $argarray, $request) {
100         if (!empty($argarray['help']))
101             return '+120'; // 2 minutes
102         return sprintf('+%d', 3*86000); // approx 3 days
103     }
104
105     /**
106      * Sets the imagetype according to user wishes and
107      * relies on WikiPluginCached to catch illegal image
108      * formats.
109      * (I feel unsure whether this option is reasonable in
110      *  this case, because png will definitely have the
111      *  best results.)
112      *
113      * @return string 'png', 'jpeg', 'gif'
114      */
115     function getImageType($dbi, $argarray, $request) {
116         return $argarray['device'];
117     }
118
119     /**
120      * This gives an alternative text description of
121      * the image.
122      */
123     function getAlt($dbi, $argstr, $request) {
124         return (!empty($this->_args['alt'])) ? $this->_args['alt']
125                                              : $this->getDescription();
126     }
127
128     /**
129      * Returns an image containing a usage description of the plugin.
130      *
131      * TODO: -csmap pointing to the Ploticus documentation at sf.net.
132      * @return string image handle
133      */
134     function helpImage() {
135         $def = $this->defaultArguments();
136         $other_imgtypes = $GLOBALS['CacheParams']['imgtypes'];
137         unset ($other_imgtypes[$def['imgtype']]);
138         $helparr = array(
139             '<?plugin Ploticus ' .
140             'device'           => ' = "' . $def['device'] . "(default)|" . join('|',$GLOBALS['CacheParams']['imgtypes']).'"',
141             'alt'              => ' = "alternate text"',
142             '-csmap'           => ' bool: clickable map?',
143             'help'             => ' bool: displays this screen',
144             '...'              => ' all further lines below the first plugin line ',
145             ''                 => ' and inside the tags are the ploticus script.',
146             "\n  ?>"
147             );
148         $length = 0;
149         foreach($helparr as $alignright => $alignleft) {
150             $length = max($length, strlen($alignright));
151         }
152         $helptext ='';
153         foreach($helparr as $alignright => $alignleft) {
154             $helptext .= substr('                                                        '
155                                 . $alignright, -$length).$alignleft."\n";
156         }
157         return $this->text2img($helptext, 4, array(1, 0, 0),
158                                array(255, 255, 255));
159     }
160  
161     function newFilterThroughCmd($input, $commandLine) {
162         $descriptorspec = array(
163                0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
164                1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
165                2 => array("pipe", "w"),  // stdout is a pipe that the child will write to
166         );
167
168         $process = proc_open("$commandLine", $descriptorspec, $pipes);
169         if (is_resource($process)) {
170             // $pipes now looks like this:
171             // 0 => writeable handle connected to child stdin
172             // 1 => readable  handle connected to child stdout
173             // 2 => readable  handle connected to child stderr
174             fwrite($pipes[0], $input);
175             fclose($pipes[0]);
176             $buf = "";
177             while(!feof($pipes[1])) {
178                 $buf .= fgets($pipes[1], 1024);
179             }
180             fclose($pipes[1]);
181             $stderr = '';
182             while(!feof($pipes[2])) {
183                 $stderr .= fgets($pipes[2], 1024);
184             }
185             fclose($pipes[2]);
186             // It is important that you close any pipes before calling
187             // proc_close in order to avoid a deadlock
188             $return_value = proc_close($process);
189             if (empty($buf)) printXML($this->error($stderr));
190             return $buf;
191         }
192     }
193
194     /* PHP versions < 4.3
195      * TODO: via temp file looks more promising
196      */
197     function OldFilterThroughCmd($input, $commandLine) {
198          $input = str_replace ("\\", "\\\\", $input);
199          $input = str_replace ("\"", "\\\"", $input);
200          $input = str_replace ("\$", "\\\$", $input);
201          $input = str_replace ("`", "\`", $input);
202          $input = str_replace ("'", "\'", $input);
203          //$input = str_replace (";", "\;", $input);
204
205          $pipe = popen("echo \"$input\"|$commandLine", 'r');
206          if (!$pipe) {
207             print "pipe failed.";
208             return "";
209          }
210          $output = '';
211          while (!feof($pipe)) {
212             $output .= fread($pipe, 1024);
213          }
214          pclose($pipe);
215          return $output;
216     }
217
218     function getImage($dbi, $argarray, $request) {
219         //extract($this->getArgs($argstr, $request));
220         //extract($argarray);
221         $source =& $this->source;
222         if (!empty($source)) {
223             $html = HTML();
224             $cacheparams = $GLOBALS['CacheParams'];
225             $tempfiles = tempnam($cacheparams['cache_dir'], 'Ploticus');
226             $gif = $argarray['device'];
227             $args = " -stdin -$gif -o $tempfiles.$gif";
228             if (!empty($argarray['-csmap'])) {
229                 $args .= " -csmap -mapfile $tempfiles.map";
230                 $this->_mapfile = "$tempfiles.map";
231             }
232             $commandLine = PLOTICUS_EXE . "$args";
233             if (check_php_version(4,3,0))
234                 $code = $this->newFilterThroughCmd($source, $commandLine);
235             else 
236                 $code = $this->oldFilterThroughCmd($source, $commandLine);
237             //if (empty($code))
238             //    return $this->error(fmt("Couldn't start commandline '%s'", $commandLine));
239             if (! file_exists("$tempfiles.$gif") )
240                 return $this->error(fmt("Ploticus error: Outputfile '%s' not created", $tempfiles.$gif));
241             $ImageCreateFromFunc = "ImageCreateFrom$gif";
242             $img = $ImageCreateFromFunc( "$tempfiles.$gif" );
243             return $img;
244         } else {
245             return $this->error(fmt("empty source"));
246         }
247     }
248     
249     function getMap($dbi, $argarray, $request) {
250         $img = $this->getImage($dbi, $argarray, $request);
251         return array($this->_mapfile, $img);
252     }
253 };
254
255 // $Log: not supported by cvs2svn $
256 // Revision 1.1  2004/06/02 19:12:42  rurban
257 // new Ploticus plugin
258 //
259 //
260
261 // For emacs users
262 // Local Variables:
263 // mode: php
264 // tab-width: 8
265 // c-basic-offset: 4
266 // c-hanging-comment-ender-p: nil
267 // indent-tabs-mode: nil
268 // End:
269 ?>