]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/Ploticus.php
include [all] Include and file path should be devided with single space. File path...
[SourceForge/phpwiki.git] / lib / plugin / Ploticus.php
1 <?php // -*-php-*-
2
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 along
19  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <<Ploticus device=png [ploticus options...]
41    multiline ploticus script ...
42 >>
43  * or without any script: (not tested)
44 <<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 //TODO: check $_ENV['PLOTICUS_PREFABS'] and default directory
57
58 require_once 'lib/WikiPluginCached.php';
59
60 class WikiPlugin_Ploticus
61 extends WikiPluginCached
62 {
63     /**
64      * Sets plugin type to MAP if -csmap (-map or -mapdemo or -csmapdemo not supported)
65      * or HTML if the imagetype is not supported by GD (EPS, SVG, SVGZ) (not yet)
66      * or IMG_INLINE if device = png, gif or jpeg
67      */
68     function getPluginType() {
69             if (!empty($this->_args['-csmap']))
70                 return PLUGIN_CACHED_MAP; // not yet tested
71         // produce these on-demand so far, uncached.
72         // will get better support in WikiPluginCached soon.
73         // FIXME: html also? what about ''?
74         $type = $this->decideImgType($this->_args['device']);
75         if ($type == $this->_args['device'])
76             return PLUGIN_CACHED_IMG_INLINE;
77         $device = strtolower($this->_args['device']);
78             if (in_array($device, array('svg','swf','svgz','eps','ps','pdf','html'))) {
79             switch ($this->_args['device']) {
80                     case 'svg':
81                     case 'svgz':
82                    return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_SVG_PNG;
83                     case 'swf':
84                    return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_SWF;
85                 default:
86                    return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_HTML;
87             }
88         }
89             else
90             return PLUGIN_CACHED_IMG_INLINE; // normal cached libgd image handles
91     }
92     function getName () {
93         return _("Ploticus");
94     }
95     function getDescription () {
96         return _("Ploticus image creation");
97     }
98     function managesValidators() {
99         return true;
100     }
101     function getDefaultArguments() {
102         return array(
103                      'device' => 'png', // png,gif,svgz,svg,...
104                      '-prefab' => '',
105                      '-csmap' => false,
106                      'data'    => false, // <!plugin-list !> support
107                      'alt'    => false,
108                      'help'   => false,
109                      );
110     }
111     function handle_plugin_args_cruft(&$argstr, &$args) {
112         $this->source = $argstr;
113     }
114     /**
115      * Sets the expire time to one day (so the image producing
116      * functions are called seldomly) or to about two minutes
117      * if a help screen is created.
118      */
119     function getExpire($dbi, $argarray, $request) {
120         if (!empty($argarray['help']))
121             return '+120'; // 2 minutes
122         return sprintf('+%d', 3*86000); // approx 3 days
123     }
124
125     /**
126      * Sets the imagetype according to user wishes and
127      * relies on WikiPluginCached to catch illegal image
128      * formats.
129      * (I feel unsure whether this option is reasonable in
130      *  this case, because png will definitely have the
131      *  best results.)
132      *
133      * @return string 'png', 'jpeg', 'gif'
134      */
135     function getImageType($dbi, $argarray, $request) {
136         return $argarray['device'];
137     }
138
139     /**
140      * This gives an alternative text description of
141      * the image.
142      */
143     function getAlt($dbi, $argstr, $request) {
144         return (!empty($this->_args['alt'])) ? $this->_args['alt']
145                                              : $this->getDescription();
146     }
147
148     /**
149      * Returns an image containing a usage description of the plugin.
150      *
151      * TODO: -csmap pointing to the Ploticus documentation at sf.net.
152      * @return string image handle
153      */
154     function helpImage() {
155         $def = $this->defaultArguments();
156         //$other_imgtypes = $GLOBALS['PLUGIN_CACHED_IMGTYPES'];
157         //unset ($other_imgtypes[$def['imgtype']]);
158         $helparr = array(
159             '<<Ploticus ' .
160             'device'           => ' = "' . $def['device'] . "(default)|"
161                                   . join('|',$GLOBALS['PLUGIN_CACHED_IMGTYPES']).'"',
162             'data'             => ' <!plugin-list !>: pagelist as input',
163             'alt'              => ' = "alternate text"',
164             '-csmap'           => ' bool: clickable map?',
165             'help'             => ' bool: displays this screen',
166             '...'              => ' all further lines below the first plugin line ',
167             ''                 => ' and inside the tags are the ploticus script.',
168             "\n  >>"
169             );
170         $length = 0;
171         foreach($helparr as $alignright => $alignleft) {
172             $length = max($length, strlen($alignright));
173         }
174         $helptext ='';
175         foreach($helparr as $alignright => $alignleft) {
176             $helptext .= substr('                                                        '
177                                 . $alignright, -$length).$alignleft."\n";
178         }
179         return $this->text2img($helptext, 4, array(1, 0, 0),
180                                array(255, 255, 255));
181     }
182
183     function withShellCommand($script) {
184         $findme  = 'shell';
185         $pos = strpos($script, $findme); // uppercase?
186         if ($pos === false)
187             return 0;
188         return 1;
189     }
190
191     function getImage($dbi, $argarray, $request) {
192         //extract($this->getArgs($argstr, $request));
193         //extract($argarray);
194         $source =& $this->source;
195         if (!empty($source)) {
196             if ($this->withShellCommand($source)) {
197                 $this->_errortext .= _("shell commands not allowed in Ploticus");
198                 return false;
199             }
200             if (is_array($argarray['data'])) { // support <!plugin-list !> pagelists
201                 $src = "#proc getdata\ndata:";
202                 $i = 0;
203                 foreach ($argarray['data'] as $data) {
204                     // hash or array?
205                     if (is_array($data))
206                         $src .= ("\t" . join(" ", $data) . "\n");
207                     else
208                         $src .= ("\t" . '"' . $data . '" ' . $i++ . "\n");
209                 }
210                 $src .= $source;
211                 $source = $src;
212             }
213             $tempfile = $this->tempnam('Ploticus','plo');
214             @unlink($tempfile);
215             $gif = $argarray['device'];
216             $args = "-$gif -o $tempfile.$gif";
217             if (!empty($argarray['-csmap'])) {
218                     $args .= " -csmap -mapfile $tempfile.map";
219                     $this->_mapfile = "$tempfile.map";
220             }
221             if (!empty($argarray['-prefab'])) {
222                     //check $_ENV['PLOTICUS_PREFABS'] and default directory
223                 global $HTTP_ENV_VARS;
224                 if (empty($HTTP_ENV_VARS['PLOTICUS_PREFABS'])) {
225                     if (file_exists("/usr/share/ploticus"))
226                         $HTTP_ENV_VARS['PLOTICUS_PREFABS'] = "/usr/share/ploticus";
227                     elseif (defined('PLOTICUS_PREFABS'))
228                         $HTTP_ENV_VARS['PLOTICUS_PREFABS'] = constant('PLOTICUS_PREFABS');
229                 }
230                     $args .= (" -prefab " . $argarray['-prefab']);
231             }
232             if (isWindows()) {
233                 $fp = fopen("$tempfile.plo", "w");
234                 fwrite ($fp, $source);
235                 fclose($fp);
236                 $code = $this->execute(PLOTICUS_EXE . " $tempfile.plo $args", $tempfile.".$gif");
237             } else {
238                 $code = $this->filterThroughCmd($source, PLOTICUS_EXE . " -stdin $args");
239                 sleep(1);
240             }
241             //if (empty($code))
242             //    return $this->error(fmt("Couldn't start commandline '%s'", $commandLine));
243             if (! file_exists($tempfile.".$gif") ) {
244                 $this->_errortext .= sprintf(_("%s error: outputfile '%s' not created"),
245                                              "Ploticus", "$tempfile.$gif");
246                 if (isWindows())
247                     $this->_errortext .= ("\ncmd-line: " .PLOTICUS_EXE . " $tempfile.plo $args");
248                 else
249                     $this->_errortext .= ("\ncmd-line: cat script | ".PLOTICUS_EXE . " $args");
250                 @unlink("$tempfile.pl");
251                 @unlink("$tempfile");
252                 return false;
253             }
254             $ImageCreateFromFunc = "ImageCreateFrom$gif";
255             if (function_exists($ImageCreateFromFunc)) {
256                 $handle = $ImageCreateFromFunc( "$tempfile.$gif" );
257                 if ($handle) {
258                     @unlink("$tempfile.$gif");
259                     @unlink("$tempfile.plo");
260                     @unlink("$tempfile");
261                     return $handle;
262                 }
263             }
264             return "$tempfile.$gif";
265         } else {
266             return $this->error(fmt("empty source"));
267         }
268     }
269
270     // which argument must be set to 'png', for the fallback image when svg will fail on the client.
271     // type: SVG_PNG
272     function pngArg() {
273             return 'device';
274     }
275
276     function getMap($dbi, $argarray, $request) {
277             $img = $this->getImage($dbi, $argarray, $request);
278             return array($this->_mapfile, $img);
279     }
280 };
281
282 // Local Variables:
283 // mode: php
284 // tab-width: 8
285 // c-basic-offset: 4
286 // c-hanging-comment-ender-p: nil
287 // indent-tabs-mode: nil
288 // End: