4 * Copyright 2004 $ThePhpWikiProgrammingTeam
6 * This file is part of PhpWiki.
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.
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.
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.
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
30 * @Author: Reini Urban
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.
40 <<Ploticus device=png [ploticus options...]
41 multiline ploticus script ...
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 >>
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.
51 if (!defined("PLOTICUS_EXE"))
53 define('PLOTICUS_EXE', 'pl.exe');
55 define('PLOTICUS_EXE', '/usr/local/bin/pl');
56 //TODO: check $_ENV['PLOTICUS_PREFABS'] and default directory
58 require_once 'lib/WikiPluginCached.php';
60 class WikiPlugin_Ploticus
61 extends WikiPluginCached
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
68 function getPluginType()
70 if (!empty($this->_args['-csmap']))
71 return PLUGIN_CACHED_MAP; // not yet tested
72 // produce these on-demand so far, uncached.
73 // will get better support in WikiPluginCached soon.
74 // FIXME: html also? what about ''?
75 $type = $this->decideImgType($this->_args['device']);
76 if ($type == $this->_args['device'])
77 return PLUGIN_CACHED_IMG_INLINE;
78 $device = strtolower($this->_args['device']);
79 if (in_array($device, array('svg', 'swf', 'svgz', 'eps', 'ps', 'pdf', 'html'))) {
80 switch ($this->_args['device']) {
83 return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_SVG_PNG;
85 return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_SWF;
87 return PLUGIN_CACHED_STATIC | PLUGIN_CACHED_HTML;
90 return PLUGIN_CACHED_IMG_INLINE; // normal cached libgd image handles
93 function getDescription()
95 return _("Ploticus image creation.");
98 function managesValidators()
103 function getDefaultArguments()
106 'device' => 'png', // png,gif,svgz,svg,...
109 'data' => false, // <!plugin-list !> support
115 function handle_plugin_args_cruft(&$argstr, &$args)
117 $this->source = $argstr;
121 * Sets the expire time to one day (so the image producing
122 * functions are called seldomly) or to about two minutes
123 * if a help screen is created.
125 function getExpire($dbi, $argarray, $request)
127 if (!empty($argarray['help']))
128 return '+120'; // 2 minutes
129 return sprintf('+%d', 3 * 86000); // approx 3 days
133 * Sets the imagetype according to user wishes and
134 * relies on WikiPluginCached to catch illegal image
136 * (I feel unsure whether this option is reasonable in
137 * this case, because png will definitely have the
141 * @param array $argarray
142 * @param Request $request
143 * @return string 'png', 'jpeg', 'gif'
145 function getImageType($dbi, $argarray, $request)
147 return $argarray['device'];
151 * This gives an alternative text description of
154 function getAlt($dbi, $argstr, $request)
156 return (!empty($this->_args['alt'])) ? $this->_args['alt']
157 : $this->getDescription();
161 * Returns an image containing a usage description of the plugin.
163 * TODO: -csmap pointing to the Ploticus documentation at sf.net.
164 * @return string image handle
168 $def = $this->defaultArguments();
169 //$other_imgtypes = $GLOBALS['PLUGIN_CACHED_IMGTYPES'];
170 //unset ($other_imgtypes[$def['imgtype']]);
173 'device' => ' = "' . $def['device'] . "(default)|"
174 . join('|', $GLOBALS['PLUGIN_CACHED_IMGTYPES']) . '"',
175 'data' => ' <!plugin-list !>: pagelist as input',
176 'alt' => ' = "alternate text"',
177 '-csmap' => ' bool: clickable map?',
178 'help' => ' bool: displays this screen',
179 '...' => ' all further lines below the first plugin line ',
180 '' => ' and inside the tags are the ploticus script.',
184 foreach ($helparr as $alignright => $alignleft) {
185 $length = max($length, strlen($alignright));
188 foreach ($helparr as $alignright => $alignleft) {
189 $helptext .= substr(' '
190 . $alignright, -$length) . $alignleft . "\n";
192 return $this->text2img($helptext, 4, array(1, 0, 0),
193 array(255, 255, 255));
196 function withShellCommand($script)
199 $pos = strpos($script, $findme); // uppercase?
205 function getImage($dbi, $argarray, $request)
207 //extract($this->getArgs($argstr, $request));
208 //extract($argarray);
209 $source =& $this->source;
210 if (!empty($source)) {
211 if ($this->withShellCommand($source)) {
212 $this->_errortext .= _("shell commands not allowed in Ploticus");
215 if (is_array($argarray['data'])) { // support <!plugin-list !> pagelists
216 $src = "#proc getdata\ndata:";
218 foreach ($argarray['data'] as $data) {
221 $src .= ("\t" . join(" ", $data) . "\n");
223 $src .= ("\t" . '"' . $data . '" ' . $i++ . "\n");
228 $tempfile = $this->tempnam('Ploticus', 'plo');
230 $gif = $argarray['device'];
231 $args = "-$gif -o $tempfile.$gif";
232 if (!empty($argarray['-csmap'])) {
233 $args .= " -csmap -mapfile $tempfile.map";
234 $this->_mapfile = "$tempfile.map";
236 if (!empty($argarray['-prefab'])) {
237 //check $_ENV['PLOTICUS_PREFABS'] and default directory
238 global $HTTP_ENV_VARS;
239 if (empty($HTTP_ENV_VARS['PLOTICUS_PREFABS'])) {
240 if (file_exists("/usr/share/ploticus"))
241 $HTTP_ENV_VARS['PLOTICUS_PREFABS'] = "/usr/share/ploticus";
242 elseif (defined('PLOTICUS_PREFABS'))
243 $HTTP_ENV_VARS['PLOTICUS_PREFABS'] = constant('PLOTICUS_PREFABS');
245 $args .= (" -prefab " . $argarray['-prefab']);
248 $fp = fopen("$tempfile.plo", "w");
249 fwrite($fp, $source);
251 $code = $this->execute(PLOTICUS_EXE . " $tempfile.plo $args", $tempfile . ".$gif");
253 $code = $this->filterThroughCmd($source, PLOTICUS_EXE . " -stdin $args");
257 // return $this->error(fmt("Couldn't start commandline ā%sā", $commandLine));
258 if (!file_exists($tempfile . ".$gif")) {
259 $this->_errortext .= sprintf(_("%s error: outputfile ā%sā not created"),
260 "Ploticus", "$tempfile.$gif");
262 $this->_errortext .= ("\ncmd-line: " . PLOTICUS_EXE . " $tempfile.plo $args");
264 $this->_errortext .= ("\ncmd-line: cat script | " . PLOTICUS_EXE . " $args");
265 @unlink("$tempfile.pl");
266 @unlink("$tempfile");
269 $ImageCreateFromFunc = "ImageCreateFrom$gif";
270 if (function_exists($ImageCreateFromFunc)) {
271 $handle = $ImageCreateFromFunc("$tempfile.$gif");
273 @unlink("$tempfile.$gif");
274 @unlink("$tempfile.plo");
275 @unlink("$tempfile");
279 return "$tempfile.$gif";
281 return $this->error(fmt("empty source"));
285 // which argument must be set to 'png', for the fallback image when svg will fail on the client.
292 function getMap($dbi, $argarray, $request)
294 $img = $this->getImage($dbi, $argarray, $request);
295 return array($this->_mapfile, $img);
303 // c-hanging-comment-ender-p: nil
304 // indent-tabs-mode: nil