]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/Ploticus.php
add SVG support for Ploticus (and hopefully all WikiPluginCached types)
[SourceForge/phpwiki.git] / lib / plugin / Ploticus.php
1 <?php // -*-php-*-
2 rcs_id('$Id: Ploticus.php,v 1.9 2004-09-26 17:09:23 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, SVG or SWF.
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 e.g. with the cygwin build.
35  * - We support only images supported by GD so far (PNG most likely). 
36  *   No EPS, PS, SWF, SVG or SVGZ support yet, due to limitations in WikiPluginCached.
37  *   This will be fixed soon.
38  *
39  * Usage:
40 <?plugin Ploticus device=png [ploticus options...]
41    multiline ploticus script ...
42 ?>
43  * or without any script: (not tested)
44 <?plugin Ploticus -prefab vbars data=myfile.dat delim=tab y=1 clickmapurl="http://mywiki.url/wiki/?pagename=@2" clickmaplabel="@3" -csmap ?>
45  *
46  * TODO: PloticusSql - create intermediate data from SQL. Similar to SqlResult, just in graphic form.
47  * For example to produce nice looking pagehit statistics or ratings statistics.
48  * Ploticus has its own sql support within #getproc data, but this would expose security information.
49  */
50
51 if (!defined("PLOTICUS_EXE"))
52   if (isWindows())
53     define('PLOTICUS_EXE','pl.exe');
54   else
55     define('PLOTICUS_EXE','/usr/local/bin/pl');
56
57 require_once "lib/WikiPluginCached.php"; 
58
59 class WikiPlugin_Ploticus
60 extends WikiPluginCached
61 {
62     /**
63      * Sets plugin type to MAP if -csmap (-map or -mapdemo or -csmapdemo not supported)
64      * or HTML if the imagetype is not supported by GD (EPS, SVG, SVGZ) (not yet)
65      * or IMG_INLINE if device = png, gif or jpeg
66      */
67     function getPluginType() {
68         if (!empty($this->_args['-csmap']))
69             return PLUGIN_CACHED_MAP; // not yet tested
70         // produce these on-demand so far, uncached. 
71         // will get better support in WikiPluginCached soon.
72         // FIXME: html also? what about ''?
73         $type = $this->decideImgType($this->_args['device']);
74         if ($type == $this->_args['device'])
75             return PLUGIN_CACHED_IMG_INLINE;
76         $device = strtolower($this->_args['device']);
77         if (in_array($device, array('svg','swf','svgz','eps','ps','pdf','html'))) {
78             switch ($this->_args['device']) {
79                 case 'svg':
80                 case 'svgz':
81                    return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_SVG_PNG;
82                 case 'swf':
83                    return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_SWF;
84                 default: 
85                    return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_HTML;
86             }
87         }
88         else
89             return PLUGIN_CACHED_IMG_INLINE; // normal cached libgd image handles
90     }
91     function getName () {
92         return _("Ploticus");
93     }
94     function getDescription () {
95         return _("Ploticus image creation");
96     }
97     function managesValidators() {
98         return true;
99     }
100     function getVersion() {
101         return preg_replace("/[Revision: $]/", '',
102                             "\$Revision: 1.9 $");
103     }
104     function getDefaultArguments() {
105         return array(
106                      'device' => 'png', // png,gif,svgz,svg,...
107                      '-prefab' => '',
108                      '-csmap' => false,
109                      'data'    => false, // <!plugin-list !> support
110                      'alt'    => false,
111                      'help'   => false,
112                      );
113     }
114     function handle_plugin_args_cruft(&$argstr, &$args) {
115         $this->source = $argstr;
116     }
117     /**
118      * Sets the expire time to one day (so the image producing
119      * functions are called seldomly) or to about two minutes
120      * if a help screen is created.
121      */
122     function getExpire($dbi, $argarray, $request) {
123         if (!empty($argarray['help']))
124             return '+120'; // 2 minutes
125         return sprintf('+%d', 3*86000); // approx 3 days
126     }
127
128     /**
129      * Sets the imagetype according to user wishes and
130      * relies on WikiPluginCached to catch illegal image
131      * formats.
132      * (I feel unsure whether this option is reasonable in
133      *  this case, because png will definitely have the
134      *  best results.)
135      *
136      * @return string 'png', 'jpeg', 'gif'
137      */
138     function getImageType($dbi, $argarray, $request) {
139         return $argarray['device'];
140     }
141
142     /**
143      * This gives an alternative text description of
144      * the image.
145      */
146     function getAlt($dbi, $argstr, $request) {
147         return (!empty($this->_args['alt'])) ? $this->_args['alt']
148                                              : $this->getDescription();
149     }
150
151     /**
152      * Returns an image containing a usage description of the plugin.
153      *
154      * TODO: -csmap pointing to the Ploticus documentation at sf.net.
155      * @return string image handle
156      */
157     function helpImage() {
158         $def = $this->defaultArguments();
159         //$other_imgtypes = $GLOBALS['PLUGIN_CACHED_IMGTYPES'];
160         //unset ($other_imgtypes[$def['imgtype']]);
161         $helparr = array(
162             '<?plugin Ploticus ' .
163             'device'           => ' = "' . $def['device'] . "(default)|" . join('|',$GLOBALS['PLUGIN_CACHED_IMGTYPES']).'"',
164             'data'             => ' <!plugin-list !>: pagelist as input',
165             'alt'              => ' = "alternate text"',
166             '-csmap'           => ' bool: clickable map?',
167             'help'             => ' bool: displays this screen',
168             '...'              => ' all further lines below the first plugin line ',
169             ''                 => ' and inside the tags are the ploticus script.',
170             "\n  ?>"
171             );
172         $length = 0;
173         foreach($helparr as $alignright => $alignleft) {
174             $length = max($length, strlen($alignright));
175         }
176         $helptext ='';
177         foreach($helparr as $alignright => $alignleft) {
178             $helptext .= substr('                                                        '
179                                 . $alignright, -$length).$alignleft."\n";
180         }
181         return $this->text2img($helptext, 4, array(1, 0, 0),
182                                array(255, 255, 255));
183     }
184
185     function withShellCommand($script) {
186         $findme  = 'shell';
187         $pos = strpos($script, $findme); // uppercase?
188         if ($pos === false) 
189             return 0;
190         return 1;
191     }
192
193     function getImage($dbi, $argarray, $request) {
194         //extract($this->getArgs($argstr, $request));
195         //extract($argarray);
196         $source =& $this->source;
197         if (!empty($source)) {
198             if ($this->withShellCommand($source)) {
199                 $this->_errortext .= _("shell commands not allowed in Ploticus");
200                 return false;
201             }
202             if (is_array($argarray['data'])) { // support <!plugin-list !> pagelists
203                 $src = "#proc getdata\ndata:";
204                 $i = 0;
205                 foreach ($argarray['data'] as $data) {
206                     // hash or array?
207                     if (is_array($data))
208                         $src .= ("\t" . join(" ", $data) . "\n");
209                     else
210                         $src .= ("\t" . '"' . $data . '" ' . $i++ . "\n");
211                 }
212                 $src .= $source;
213                 $source = $src;
214             }
215             $tempfile = $this->tempnam('Ploticus');
216             unlink($tempfile);
217             $gif = $argarray['device'];
218             $args = " -stdin -$gif -o $tempfile.$gif";
219             if (!empty($argarray['-csmap'])) {
220                 $args .= " -csmap -mapfile $tempfile.map";
221                 $this->_mapfile = "$tempfile.map";
222             }
223             if (!empty($argarray['-prefab'])) {
224                 //TODO: check $_ENV['PLOTICUS_PREFABS'] and default directory
225                 $args .= (" -prefab " . $argarray['-prefab']);
226             }
227             $code = $this->filterThroughCmd($source, PLOTICUS_EXE . "$args");
228             //if (empty($code))
229             //    return $this->error(fmt("Couldn't start commandline '%s'", $commandLine));
230             if (! file_exists("$tempfile.$gif") ) {
231                 $this->_errortext .= sprintf(_("Ploticus error: Outputfile '%s' not created"), "$tempfile.$gif");
232                 return false;
233             }
234             $ImageCreateFromFunc = "ImageCreateFrom$gif";
235             if (function_exists($ImageCreateFromFunc))
236                 return $ImageCreateFromFunc( "$tempfile.$gif" );
237             return "$tempfile.$gif";
238         } else {
239             return $this->error(fmt("empty source"));
240         }
241     }
242     
243     // which argument must be set to 'png', for the fallback image when svg will fail on the client.
244     // type: SVG_PNG
245     function pngArg() {
246         return 'device';
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.8  2004/09/22 15:23:56  rurban
257 // support <!plugin-list !> pagelist data
258 // add -prefab arg support
259 //
260 // Revision 1.7  2004/09/22 13:46:26  rurban
261 // centralize upload paths.
262 // major WikiPluginCached feature enhancement:
263 //   support _STATIC pages in uploads/ instead of dynamic getimg.php? subrequests.
264 //   mainly for debugging, cache problems and action=pdf
265 //
266 // Revision 1.6  2004/09/07 13:26:31  rurban
267 // new WikiPluginCached option debug=static and some more sf.net defaults for VisualWiki
268 //
269 // Revision 1.5  2004/06/28 16:35:12  rurban
270 // prevent from shell commands
271 //
272 // Revision 1.4  2004/06/19 10:06:38  rurban
273 // Moved lib/plugincache-config.php to config/*.ini
274 // use PLUGIN_CACHED_* constants instead of global $CacheParams
275 //
276 // Revision 1.3  2004/06/03 09:40:57  rurban
277 // WikiPluginCache improvements
278 //
279 // Revision 1.2  2004/06/02 19:37:07  rurban
280 // extended description
281 //
282 // Revision 1.1  2004/06/02 19:12:42  rurban
283 // new Ploticus plugin
284 //
285 //
286
287 // For emacs users
288 // Local Variables:
289 // mode: php
290 // tab-width: 8
291 // c-basic-offset: 4
292 // c-hanging-comment-ender-p: nil
293 // indent-tabs-mode: nil
294 // End:
295 ?>