00001 <?php
00017 class SRFPloticus extends SMWResultPrinter {
00018 protected $m_ploticusparams = '';
00019 protected $m_imageformat = 'gif';
00020 protected $m_titletext = '';
00021 protected $m_showcsv = false;
00022 protected $m_debug = false;
00023 protected $m_liveupdating = true;
00024 protected $m_updatefrequency = 3600;
00025 protected $m_showtimestamp = false;
00026 protected $m_showrefresh = false;
00027 protected $m_showimagelink = false;
00028 protected $m_drawdumpoutput = '';
00029 protected $m_tblwidth = '';
00030 protected $m_tblheight = '';
00031 protected $m_width = '';
00032 protected $m_height = '';
00033
00034 protected function readParameters( $params, $outputmode ) {
00035 parent::readParameters( $params, $outputmode );
00036 if ( array_key_exists( 'ploticusparams', $this->m_params ) ) {
00037 $this->m_ploticusparams = trim( $params['ploticusparams'] );
00038 }
00039 if ( array_key_exists( 'imageformat', $this->m_params ) ) {
00040 $this->m_imageformat = strtolower( trim( $params['imageformat'] ) );
00041 }
00042 if ( array_key_exists( 'titletext', $this->m_params ) ) {
00043 $this->m_titletext = trim( $params['titletext'] );
00044 }
00045 if ( array_key_exists( 'showcsv', $this->m_params ) ) {
00046 $tmpcmp = strtolower( trim( $params['showcsv'] ) );
00047 $this->m_showcsv = $tmpcmp == 'false' || $tmpcmp == 'no' ? false : $tmpcmp;
00048 }
00049 if ( array_key_exists( 'debug', $this->m_params ) ) {
00050 $tmpcmp = strtolower( trim( $params['debug'] ) );
00051 $this->m_debug = $tmpcmp == 'false' || $tmpcmp == 'no' ? false : $tmpcmp;
00052 }
00053 if ( array_key_exists( 'liveupdating', $this->m_params ) ) {
00054 $tmpcmp = strtolower( trim( $params['liveupdating'] ) );
00055 $this->m_liveupdating = $tmpcmp == 'false' || $tmpcmp == 'no' ? false : $tmpcmp;
00056 }
00057 if ( array_key_exists( 'updatefrequency', $this->m_params ) ) {
00058 $this->m_updatefrequency = trim( $params['updatefrequency'] );
00059 }
00060 if ( array_key_exists( 'showtimestamp', $this->m_params ) ) {
00061 $tmpcmp = strtolower( trim( $params['showtimestamp'] ) );
00062 $this->m_showtimestamp = $tmpcmp == 'false' || $tmpcmp == 'no' ? false : $tmpcmp;
00063 }
00064 if ( array_key_exists( 'showrefresh', $this->m_params ) ) {
00065 $tmpcmp = strtolower( trim( $params['showrefresh'] ) );
00066 $this->m_showrefresh = $tmpcmp == 'false' || $tmpcmp == 'no' ? false : $tmpcmp;
00067 }
00068 if ( array_key_exists( 'showimagelink', $this->m_params ) ) {
00069 $tmpcmp = strtolower( trim( $params['showimagelink'] ) );
00070 $this->m_showimagelink = $tmpcmp == 'false' || $tmpcmp == 'no' ? false : $tmpcmp;
00071 }
00072 if ( array_key_exists( 'drawdumpoutput', $this->m_params ) ) {
00073 $this->m_drawdumpoutput = trim( $params['drawdumpoutput'] );
00074 }
00075 if ( array_key_exists( 'tblwidth', $this->m_params ) ) {
00076 $this->m_tblwidth = trim( $params['tblwidth'] );
00077 }
00078 if ( array_key_exists( 'tblheight', $this->m_params ) ) {
00079 $this->m_tblheight = trim( $params['tblheight'] );
00080 }
00081 if ( array_key_exists( 'width', $this->m_params ) ) {
00082 $this->m_width = trim( $params['width'] );
00083 }
00084 if ( array_key_exists( 'height', $this->m_params ) ) {
00085 $this->m_height = trim( $params['height'] );
00086 }
00087 }
00088
00089 protected function getResultText( SMWQueryResult $res, $outputmode ) {
00090 global $smwgIQRunningNumber, $wgUploadDirectory, $wgUploadPath, $wgTitle, $wgScriptPath, $srfgPloticusPath, $srfgEnvSettings;
00091
00092 $this->isHTML = true;
00093 $this->outputmode = SMW_OUTPUT_HTML;
00094
00095
00096 $validformats = array( 'svg', 'svgz', 'swf', 'png', 'gif', 'jpeg', 'drawdump', 'drawdumpa', 'eps', 'ps' );
00097 if ( !in_array( $this->m_imageformat, $validformats ) )
00098 return ( '<p classid="srfperror">ERROR: ' . $this->m_imageformat . ' is not a supported imageformat.<br />Valid imageformats are: ' .
00099 implode( ', ', $validformats ) . '</p>' );
00100
00101 if ( empty( $this->m_ploticusparams ) )
00102 return ( '<p classid="srfperror">ERROR: <em>ploticusparams</em> required.</p>' );
00103
00104 if ( empty( $srfgPloticusPath ) )
00105 return ( '<p classid="srfperror">ERROR: Set $srfgPloticusPath in LocalSettings.php (e.g. $srfgPloticusPath=/usr/bin/pl).</p>' );
00106
00107 if ( !file_exists( $srfgPloticusPath ) )
00108 return ( '<p classid=""srfperror">ERROR: Could not find ploticus in <em>' . $srfgPloticusPath . '</em></p>' );
00109
00110
00111
00112
00113
00114 $searches = array( '/`/m', '/system/im', '/shell/im', "/\s*?\n/m" );
00115 $replaces = array( '', '', '', ' ' );
00116 $sanitized_ploticusparams = preg_replace( $searches, $replaces, $this->m_ploticusparams );
00117
00118
00119
00120 $ploticusDir = $wgUploadDirectory . '/ploticus/';
00121 if ( !is_dir( $ploticusDir ) ) {
00122 mkdir( $ploticusDir, 0777 );
00123 for ( $idx = 0; $idx < 16; $idx++ )
00124 mkdir( $ploticusDir . dechex( $idx ), 0777 );
00125 }
00126
00127
00128 $tmpFile = tempnam( $ploticusDir, 'srf-' );
00129 if ( ( $fhandle = fopen( $tmpFile, 'w' ) ) === false )
00130 return ( '<p class="srfperror">ERROR: Cannot create data file - ' . $tmpFile . '. Check permissions.</p>' );
00131
00132 if ( $this->mShowHeaders ) {
00133
00134 $header_row = array();
00135 foreach ( $res->getPrintRequests() as $pr ) {
00136 $headertext = $pr->getLabel();
00137 $header_row[] = strtr( $headertext, " ,", "_|" );
00138 }
00139 if ( empty( $header_row[0] ) )
00140 $header_row[0] = "Article";
00141 fputcsv( $fhandle, $header_row );
00142 }
00143
00144 while ( $row = $res->getNext() ) {
00145 $row_items = array();
00146 foreach ( $row as $field ) {
00147 $growing = array();
00148
00149 while ( ( $object = $field->getNextDataValue() ) !== false ) {
00150 $text = Sanitizer::decodeCharReferences( $object->getXSDValue() );
00151
00152 $growing[] = $text;
00153 }
00154 $row_items[] = implode( ',', $growing );
00155 }
00156 fputcsv( $fhandle, $row_items );
00157 }
00158 fclose( $fhandle );
00159
00160
00161
00162 $hashname = hash( 'md5', $wgTitle->getPrefixedDBkey() . $smwgIQRunningNumber . implode( ',', $this->m_params ) );
00163 if ( $this->m_liveupdating ) {
00164
00165
00166 $hashname .= hash_file( 'md5', $tmpFile );
00167 }
00168
00169 $orighash = $hashname;
00170
00171 $hashname = substr( $hashname, 0, 1 ) . '/' . $hashname;
00172 $dataFile = $ploticusDir . $hashname . '.csv';
00173 @unlink( $dataFile );
00174 @rename( $tmpFile, $dataFile );
00175 $dataURL = $wgUploadPath . '/ploticus/' . $hashname . '.csv';
00176 $srficonPath = $wgScriptPath . '/extensions/SemanticResultFormats/Ploticus/icons/';
00177
00178 $graphFile = $ploticusDir . $hashname . '.' . $this->m_imageformat;
00179 $graphURL = $wgUploadPath . '/ploticus/' . $hashname . '.' . $this->m_imageformat;
00180 $errorFile = $ploticusDir . $hashname . '.err';
00181 $errorURL = $wgUploadPath . '/ploticus/' . $hashname . '.err';
00182 $mapFile = $ploticusDir . $hashname . '.map';
00183 $mapURL = $wgUploadPath . '/ploticus/' . $hashname . '.map';
00184
00185 if ( ( $this->m_updatefrequency > 0 ) && file_exists( $graphFile ) ) {
00186
00187
00188 $graphLastGenerated = filemtime( $graphFile );
00189 $expireTime = $graphLastGenerated + $this->m_updatefrequency;
00190 if ( $expireTime < time() ) {
00191 @unlink( $graphFile );
00192 }
00193 }
00194
00195
00196
00197
00198
00199 $errorData = '';
00200 if ( $this->m_debug || !file_exists( $graphFile ) ) {
00201
00202
00203 $commandline = empty( $srfgEnvSettings ) ? ' ' : $srfgEnvSettings . ' ';
00204
00205
00206
00207 $commandline .= wfEscapeShellArg( $srfgPloticusPath ) .
00208 ( $this->m_debug ? ' -debug':' ' ) .
00209 ' -noshell ' . $sanitized_ploticusparams .
00210 ( $this->mShowHeaders ? ' header=yes':' ' ) .
00211 ' delim=comma data=' . wfEscapeShellArg( $dataFile ) .
00212 ' -' . $this->m_imageformat;
00213
00214 if ( $this->m_imageformat == 'drawdump' || $this->m_imageformat == 'drawdumpa' ) {
00215 $commandline .= ' ' . wfEscapeShellArg( $ploticusDir . '/' . $this->m_drawdumpoutput );
00216 } else {
00217 $commandline .= ' -o ' . wfEscapeShellArg( $graphFile );
00218 }
00219
00220
00221 if ( strpos( $sanitized_ploticusparams, 'clickmap' ) ) {
00222 $commandline .= ' >' . wfEscapeShellArg( $mapFile );
00223 }
00224
00225
00226 $commandline .= ' 2>' . wfEscapeShellArg( $errorFile );
00227
00228
00229 $commandline = escapeshellcmd( $commandline );
00230
00231 wfShellExec( $commandline );
00232 $errorData = file_get_contents( $errorFile );
00233 if ( !$this->m_debug )
00234 @unlink( $errorFile );
00235
00236 $graphLastGenerated = time();
00237
00238 }
00239
00240
00241
00242 $rtnstr = '<table class="srfptable" id="srfptblid' . $smwgIQRunningNumber . '" cols="3"' .
00243 ( empty( $this->m_tblwidth ) ? ' ' : ' width="' . $this->m_tblwidth . '" ' ) .
00244 ( empty( $this->m_tblheight ) ? ' ' : ' height="' . $this->m_tblheight . '" ' ) .
00245 '><tr>';
00246 if ( !empty( $errorData ) && !$this->m_debug ) {
00247
00248
00249 $rtnstr .= '<td class="srfperror" colspan="3">Error processing ploticus data:</td></tr><tr><td class="srfperror" colspan="3" align="center">' .
00250 $errorData . '</td></tr>';
00251 } else {
00252 $rtnstr .= '<td class="srfpplot" colspan="3" align="center">';
00253 switch ( $this->m_imageformat ) {
00254 case 'svg':
00255 case 'svgz':
00256 $rtnstr .= '<object data="' . $graphURL . '"' .
00257 ( empty( $this->m_width ) ? ' ' : ' width="' . $this->m_width . '" ' ) .
00258 ( empty( $this->m_height ) ? ' ' : ' height="' . $this->m_height . '" ' ) .
00259 'type="image/svg+xml"><param name="src" value="' . $graphURL .
00260 '"> alt : <a href="' . $graphURL . '">Requires SVG capable browser</a></object>';
00261 break;
00262 case 'swf':
00263 $rtnstr .= '<object type="application/x-shockwave-flash" data="' . $graphURL . '"' .
00264 ( empty( $this->m_width ) ? ' ' : ' width="' . $this->m_width . '" ' ) .
00265 ( empty( $this->m_height ) ? ' ' : ' height="' . $this->m_height . '" ' ) .
00266 '><param name="movie" value="' . $graphURL .
00267 '"><param name="loop" value="false"><param name="SCALE" value="noborder"> alt : <a href="' . $graphURL .
00268 '">Requires Adobe Flash plugin</a></object>';
00269 break;
00270 case 'png':
00271 case 'gif':
00272 case 'jpeg':
00273 if ( strpos( $sanitized_ploticusparams, 'clickmap' ) ) {
00274
00275 $mapData = file_get_contents( $mapFile );
00276 $rtnstr .= '<map name="' . $orighash . '">' . $mapData .
00277 '</map><img src="' . $graphURL . '" border="0" usemap="#' . $orighash . '">';
00278 } else {
00279 $rtnstr .= '<img src="' . $graphURL . '" alt="' . $this->m_titletext . '" title="' . $this->m_titletext . '">';
00280 }
00281 break;
00282 case 'eps':
00283 case 'ps':
00284 $rtnstr .= '<object type="application/postscript" data="' . $graphURL . '"' .
00285 ( empty( $this->m_width ) ? ' ' : ' width="' . $this->m_width . '" ' ) .
00286 ( empty( $this->m_height ) ? ' ' : ' height="' . $this->m_height . '" ' ) .
00287 '> alt : <a href="' . $graphURL . '">Requires PDF-capable browser</a></object>';
00288 }
00289 $rtnstr .= '</td></tr>';
00290 }
00291
00292 $rtnstr .= '<tr><td class="srfpaction" width="33%" colspan="1">';
00293
00294
00295
00296 if ( $this->m_showcsv || $this->m_debug ) {
00297 $rtnstr .= '<a href="' . $dataURL . '" title="CSV file"><img src="' .
00298 $srficonPath . 'csv_16.png" alt="CSV file"></a>';
00299 } else {
00300 @unlink( $dataFile );
00301 }
00302
00303
00304 if ( $this->m_showimagelink ) {
00305 $rtnstr .= ' <a href="' . $graphURL . '" target="_blank" title="Open image in new window"><img src="' .
00306 $srficonPath . 'barchart_16.png" alt="Open image in new window"></a>';
00307 }
00308
00309
00310 if ( $this->m_showrefresh ) {
00311 global $wgArticlePath;
00312 $rtnstr .= ' <a href="' . $wgArticlePath . '?action=purge" title="Reload"><img src="' .
00313 $srficonPath . 'reload_16.png" alt="Reload"></a>';
00314 }
00315
00316
00317
00318 $rtnstr .= '</td><td class="srfptitle" width="33%" colspan="1" align="center">' . $this->m_titletext;
00319
00320
00321
00322 $rtnstr .= '</td><td class="srfptimestamp" width="33%" colspan="1" align="right">';
00323 if ( $this->m_showtimestamp ) {
00324 $rtnstr .= '<small> Generated: ' . date( 'Y-m-d h:i:s A', $graphLastGenerated ) . '</small>';
00325 }
00326
00327 $rtnstr .= '</td></tr>';
00328
00329
00330
00331 if ( $this->m_debug ) {
00332 $rtnstr .= '<tr><td class="srfpdebug" align="center" colspan="3">DEBUG: PREFAB (<a href=" ' . $errorURL .
00333 '" target="_blank">Ploticus Trace</a>)</td></tr><tr><td class="srfpdebug" colspan="3">' .
00334 $commandline . '</td></tr>';
00335 }
00336
00337 $rtnstr .= '</table>';
00338
00339 return ( $rtnstr );
00340 }
00341
00342 function getParameters() {
00343 return array(
00344 array('name' => 'ploticusmode', 'type' => 'enumeration', 'values' => array('preftab', 'script')),
00345 array('name' => 'ploticusparams', 'type' => 'string'),
00346 array('name' => 'imageformat', 'type' => 'enumeration', 'values' => array('png', ' gif', 'jpeg', 'svg', 'svgz', 'swf', 'eps', 'ps', 'drawdump', 'drawdumpa'), 'defaultValue'=>'png'),
00347 array('name' => 'titletext', 'type' => 'string'),
00348 array('name' => 'showcsv', 'type' => 'boolean'),
00349 array('name' => 'ploticusmode', 'type' => 'string'),
00350 array('name' => 'debug', 'type' => 'boolean'),
00351 array('name' => 'liveupdating', 'type' => 'boolean'),
00352 array('name' => 'updatefrequency', 'type' => 'int'),
00353 array('name' => 'showtimestamp', 'type' => 'boolean'),
00354 array('name' => 'showimagelink', 'type' => 'boolean'),
00355 array('name' => 'showrefresh', 'type' => 'boolean'),
00356 array('name' => 'drawdumpoutput', 'type' => 'string'),
00357 array('name' => 'tblwidth', 'type' => 'int'),
00358 array('name' => 'tblheight', 'type' => 'int'),
00359 array('name' => 'width', 'type' => 'int'),
00360 array('name' => 'height', 'type' => 'int')
00361 );
00362 }
00363
00364 }