[ Index ] |
|
Code source de Mantis 1.1.0rc3 |
1 <?php 2 # Mantis - a php based bugtracking system 3 4 # Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 5 # Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net 6 7 # Mantis is free software: you can redistribute it and/or modify 8 # it under the terms of the GNU General Public License as published by 9 # the Free Software Foundation, either version 2 of the License, or 10 # (at your option) any later version. 11 # 12 # Mantis is distributed in the hope that it will be useful, 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # GNU General Public License for more details. 16 # 17 # You should have received a copy of the GNU General Public License 18 # along with Mantis. If not, see <http://www.gnu.org/licenses/>. 19 20 # -------------------------------------------------------- 21 # $Id: graphviz_api.php,v 1.6.2.1 2007-10-13 22:35:30 giallu Exp $ 22 # -------------------------------------------------------- 23 24 ### GraphViz API ### 25 26 # ================================================================ 27 # Author: Juliano Ravasi Ferraz <jferraz at users sourceforge net> 28 # ================================================================ 29 # 30 # Wrapper classes around GraphViz utilities (dot and neato) for 31 # directed and undirected graph generation. Under Windows, the COM 32 # API provided by WinGraphviz is used. These wrappers are enhanced 33 # enough just to support relationship_graph_api.php. They don't 34 # support subgraphs yet. 35 # 36 # The original Graphviz package is available at: 37 # - http://www.research.att.com/sw/tools/graphviz/ 38 # 39 # WinGraphviz can be installed from: 40 # - http://home.so-net.net.tw/oodtsen/wingraphviz/ 41 # 42 # Additional documentation can be found at: 43 # - http://www.graphviz.org/Documentation.html 44 45 # -------------------- 46 # These constants define the output formats supported by dot and neato. 47 define( 'GRAPHVIZ_ATTRIBUTED_DOT', 0 ); 48 define( 'GRAPHVIZ_PS', 1 ); 49 define( 'GRAPHVIZ_HPGL', 2 ); 50 define( 'GRAPHVIZ_PCL', 3 ); 51 define( 'GRAPHVIZ_MIF', 4 ); 52 define( 'GRAPHVIZ_PLAIN', 6 ); 53 define( 'GRAPHVIZ_PLAIN_EXT', 7 ); 54 define( 'GRAPHVIZ_GIF', 11 ); 55 define( 'GRAPHVIZ_JPEG', 12 ); 56 define( 'GRAPHVIZ_PNG', 13 ); 57 define( 'GRAPHVIZ_WBMP', 14 ); 58 define( 'GRAPHVIZ_XBM', 15 ); 59 define( 'GRAPHVIZ_ISMAP', 16 ); 60 define( 'GRAPHVIZ_IMAP', 17 ); 61 define( 'GRAPHVIZ_CMAP', 18 ); 62 define( 'GRAPHVIZ_CMAPX', 19 ); 63 define( 'GRAPHVIZ_VRML', 20 ); 64 define( 'GRAPHVIZ_SVG', 25 ); 65 define( 'GRAPHVIZ_SVGZ', 26 ); 66 define( 'GRAPHVIZ_CANONICAL_DOT', 27 ); 67 define( 'GRAPHVIZ_PDF', 28 ); 68 69 # -------------------- 70 # Base class for graph creation and manipulation. By default, 71 # undirected graphs are generated. For directed graphs, use Digraph 72 # class. 73 class Graph { 74 var $name = 'G'; 75 var $attributes = array(); 76 var $default_node = null; 77 var $default_edge = null; 78 var $nodes = array(); 79 var $edges = array(); 80 81 var $graphviz_tool; 82 var $graphviz_com_module; 83 84 var $formats = array ( 85 'dot' => array ( 86 'binary'=> false, 87 'type' => GRAPHVIZ_ATTRIBUTED_DOT, 88 'mime' => 'text/x-graphviz' 89 ), 90 'ps' => array ( 91 'binary'=> false, 92 'type' => GRAPHVIZ_PS, 93 'mime' => 'application/postscript' 94 ), 95 'hpgl' => array ( 96 'binary'=> true, 97 'type' => GRAPHVIZ_HPGL, 98 'mime' => 'application/vnd.hp-HPGL' 99 ), 100 'pcl' => array ( 101 'binary'=> true, 102 'type' => GRAPHVIZ_PCL, 103 'mime' => 'application/vnd.hp-PCL' 104 ), 105 'mif' => array ( 106 'binary'=> true, 107 'type' => GRAPHVIZ_MIF, 108 'mime' => 'application/vnd.mif' 109 ), 110 'gif' => array ( 111 'binary'=> true, 112 'type' => GRAPHVIZ_GIF, 113 'mime' => 'image/gif' 114 ), 115 'jpg' => array ( 116 'binary'=> false, 117 'type' => GRAPHVIZ_JPEG, 118 'mime' => 'image/jpeg' 119 ), 120 'jpeg' => array ( 121 'binary'=> true, 122 'type' => GRAPHVIZ_JPEG, 123 'mime' => 'image/jpeg' 124 ), 125 'png' => array ( 126 'binary'=> true, 127 'type' => GRAPHVIZ_PNG, 128 'mime' => 'image/png' 129 ), 130 'wbmp' => array ( 131 'binary'=> true, 132 'type' => GRAPHVIZ_WBMP, 133 'mime' => 'image/vnd.wap.wbmp' 134 ), 135 'xbm' => array ( 136 'binary'=> false, 137 'type' => GRAPHVIZ_XBM, 138 'mime' => 'image/x-xbitmap' 139 ), 140 'ismap' => array ( 141 'binary'=> false, 142 'type' => GRAPHVIZ_ISMAP, 143 'mime' => 'text/plain' 144 ), 145 'imap' => array ( 146 'binary'=> false, 147 'type' => GRAPHVIZ_IMAP, 148 'mime' => 'application/x-httpd-imap' 149 ), 150 'cmap' => array ( 151 'binary'=> false, 152 'type' => GRAPHVIZ_CMAP, 153 'mime' => 'text/html' 154 ), 155 'cmapx' => array ( 156 'binary'=> false, 157 'type' => GRAPHVIZ_CMAPX, 158 'mime' => 'application/xhtml+xml' 159 ), 160 'vrml' => array ( 161 'binary'=> true, 162 'type' => GRAPHVIZ_VRML, 163 'mime' => 'x-world/x-vrml' 164 ), 165 'svg' => array ( 166 'binary'=> false, 167 'type' => GRAPHVIZ_SVG, 168 'mime' => 'image/svg+xml' 169 ), 170 'svgz' => array ( 171 'binary'=> true, 172 'type' => GRAPHVIZ_SVGZ, 173 'mime' => 'image/svg+xml' 174 ), 175 'pdf' => array ( 176 'binary'=> true, 177 'type' => GRAPHVIZ_PDF, 178 'mime' => 'application/pdf' 179 ) 180 ); 181 182 # -------------------- 183 # Constructor for Graph objects. 184 function Graph( $p_name = 'G', $p_attributes = array(), $p_tool = 'neato', 185 $p_com_module = 'WinGraphviz.NEATO' ) { 186 if ( is_string( $p_name ) ) 187 $this->name = $p_name; 188 189 $this->set_attributes( $p_attributes ); 190 191 $this->graphviz_tool = $p_tool; 192 $this->graphviz_com_module = $p_com_module; 193 } 194 195 # -------------------- 196 # Sets graph attributes. 197 function set_attributes( $p_attributes ) { 198 if ( is_array( $p_attributes ) ) 199 $this->attributes = $p_attributes; 200 } 201 202 # -------------------- 203 # Sets default attributes for all nodes of the graph. 204 function set_default_node_attr( $p_attributes ) { 205 if ( is_array( $p_attributes ) ) 206 $this->default_node = $p_attributes; 207 } 208 209 # -------------------- 210 # Sets default attributes for all edges of the graph. 211 function set_default_edge_attr( $p_attributes ) { 212 if ( is_array( $p_attributes ) ) 213 $this->default_edge = $p_attributes; 214 } 215 216 # -------------------- 217 # Adds a node to the graph. 218 function add_node( $p_name, $p_attributes = array() ) { 219 if ( is_array( $p_attributes ) ) 220 $this->nodes[$p_name] = $p_attributes; 221 } 222 223 # -------------------- 224 # Adds an edge to the graph. 225 function add_edge( $p_src, $p_dst, $p_attributes = array() ) { 226 if ( is_array( $p_attributes ) ) 227 $this->edges[] = array ( 228 'src' => $p_src, 229 'dst' => $p_dst, 230 'attributes' => $p_attributes 231 ); 232 } 233 234 # -------------------- 235 # Check if an edge is already present. 236 function is_edge_present( $p_src, $p_dst ) { 237 foreach( $this->edges as $t_edge ) { 238 if( $t_edge['src'] == $p_src && $t_edge['dst'] == $p_dst ) { 239 return true; 240 } 241 } 242 return false; 243 } 244 245 # -------------------- 246 # Generates an undirected graph representation (suitable for neato). 247 function generate() { 248 echo 'graph ' . $this->name . ' {' . "\n"; 249 250 $this->_print_graph_defaults(); 251 252 foreach ( $this->nodes as $t_name => $t_attr ) { 253 $t_name = '"' . addcslashes( $t_name, "\0..\37\"\\") . '"'; 254 $t_attr = $this->_build_attribute_list( $t_attr ); 255 echo "\t" . $t_name . ' ' . $t_attr . ";\n"; 256 } 257 258 foreach ( $this->edges as $t_edge ) { 259 $t_src = '"' . addcslashes( $t_edge['src'], "\0..\37\"\\") . '"'; 260 $t_dst = '"' . addcslashes( $t_edge['dst'], "\0..\37\"\\") . '"'; 261 $t_attr = $t_edge['attributes']; 262 $t_attr = $this->_build_attribute_list( $t_attr ); 263 echo "\t" . $t_src . ' -- ' . $t_dst . ' ' . $t_attr . ";\n"; 264 } 265 266 echo "};\n"; 267 } 268 269 # -------------------- 270 # Outputs a graph image or map in the specified format. 271 function output( $p_format = 'dot', $p_headers = false ) { 272 # Check if it is a recognized format. 273 if ( !isset( $this->formats[$p_format] ) ) 274 trigger_error( ERROR_GENERIC, ERROR ); 275 276 $t_binary = $this->formats[$p_format]['binary']; 277 $t_type = $this->formats[$p_format]['type']; 278 $t_mime = $this->formats[$p_format]['mime']; 279 280 # Send Content-Type header, if requested. 281 if ( $p_headers ) 282 header( 'Content-Type: ' . $t_mime ); 283 284 # Retrieve the source dot document into a buffer 285 ob_start(); 286 $this->generate(); 287 $t_dot_source = ob_get_contents(); 288 ob_end_clean(); 289 290 # There are three different ways to generate the output depending 291 # on the operating system and PHP version. 292 if ( 'WIN' == substr( PHP_OS, 0, 3 ) ) { 293 # If we are under Windows, we use the COM interface provided 294 # by WinGraphviz. Thanks Paul! 295 # Issue #4625: Work around WinGraphviz bug that fails with 296 # graphs with zero or one node. It is probably too much to 297 # generate a graphic output just to explain it to the user, 298 # so we just return a null content. 299 if ( count( $this->nodes ) <= 1 ) 300 return; 301 302 $t_graphviz = new COM( $this->graphviz_com_module ); 303 304 # Check if we managed to instantiate the COM object. 305 if ( is_null( $t_graphviz ) ) { 306 # We can't display any message or trigger an error on 307 # failure, since we may have already sent a Content-type 308 # header potentially incompatible with the any html output. 309 return; 310 } 311 312 if ( $t_binary ) { 313 # Image formats 314 $t_dot_output = $t_graphviz->ToBinaryGraph( $t_dot_source, $t_type ); 315 316 if ( $p_headers ) { 317 # Headers were requested, use another output buffer 318 # to retrieve the size for Content-Length. 319 ob_start(); 320 echo base64_decode( $t_dot_output->ToBase64String() ); 321 header( 'Content-Length: ' . ob_get_length() ); 322 ob_end_flush(); 323 } else { 324 # No need for headers, send output directly. 325 echo base64_decode( $ret->ToBase64String() ); 326 } 327 } else { 328 # Text formats 329 $t_dot_output = $t_graphviz->ToTextGraph( $t_dot_source, $t_type ); 330 331 if ( $p_headers ) 332 header( 'Content-Length: ' . strlen( $t_dot_output ) ); 333 334 echo $t_dot_output; 335 } 336 337 unset($t_graphviz); 338 } else if ( php_version_at_least( '4.3.0' ) ) { 339 # If we are not under Windows, use proc_open whenever possible, 340 # (PHP >= 4.3.0) since it avoids the need of temporary files. 341 342 # Start dot process 343 $t_command = $this->graphviz_tool . ' -T' . $p_format; 344 $t_descriptors = array ( 345 0 => array ( 'pipe', 'r' ), 346 1 => array ( 'pipe', 'w' ), 347 2 => array ( 'file', 'php://stderr', 'w' ) 348 ); 349 350 $t_proccess = proc_open( $t_command, $t_descriptors, $t_pipes ); 351 352 if ( is_resource( $t_proccess ) ) { 353 # Filter generated output through dot 354 fwrite( $t_pipes[0], $t_dot_source ); 355 fclose( $t_pipes[0] ); 356 357 if ( $p_headers ) { 358 # Headers were requested, use another output buffer to 359 # retrieve the size for Content-Length. 360 ob_start(); 361 while ( !feof( $t_pipes[1] ) ) 362 echo fgets( $t_pipes[1], 1024 ); 363 header( 'Content-Length: ' . ob_get_length() ); 364 ob_end_flush(); 365 } else { 366 # No need for headers, send output directly. 367 while ( !feof( $t_pipes[1] ) ) 368 print( fgets( $t_pipes[1], 1024 ) ); 369 } 370 371 fclose( $t_pipes[1] ); 372 proc_close( $t_proccess ); 373 } 374 } else { 375 # If proc_open is not available (PHP < 4.3.0), use passthru. 376 # @@@ Remove this whole block once Mantis PHP requirements 377 # @@@ becomes higher. 378 379 # We need a temporary file. 380 if ( isset( $_ENV['TMPDIR'] ) ) 381 $t_tmpdir = $_ENV['TMPDIR']; 382 else 383 $t_tmpdir = '/tmp'; 384 385 $t_filename = tempnam( $t_tmpdir, 'mantis-dot-' ); 386 register_shutdown_function( 'unlink', $t_filename ); 387 388 if ( $t_file = @fopen( $t_filename, 'w' ) ) { 389 fputs( $t_file, $t_dot_source ); 390 fclose( $t_file ); 391 } 392 393 # Now we process it through dot or neato 394 $t_command = $this->graphviz_tool . ' -T' . $p_format . ' ' . 395 $t_filename; 396 397 if ( $p_headers ) { 398 # Headers were requested, use another output buffer to 399 # retrieve the size for Content-Length. 400 ob_start(); 401 passthru( $t_command ); 402 header( 'Content-Length: ' . ob_get_length() ); 403 ob_end_flush(); 404 } else { 405 # No need for headers, send output directly. 406 passthru( $t_command ); 407 } 408 } 409 } 410 411 # -------------------- 412 # PROTECTED function to build a node or edge attribute list. 413 function _build_attribute_list( $p_attributes ) { 414 if ( empty( $p_attributes ) ) 415 return ''; 416 417 $t_result = array ( ); 418 419 foreach ( $p_attributes as $t_name => $t_value ) { 420 if ( !ereg( "[a-zA-Z]+", $t_name ) ) 421 continue; 422 423 if ( is_string( $t_value ) ) 424 $t_value = '"' . addcslashes( $t_value, "\0..\37\"\\") . '"'; 425 else if ( is_integer( $t_value ) or is_float( $t_value ) ) 426 $t_value = (string) $t_value; 427 else 428 continue; 429 430 $t_result[] = $t_name . '=' . $t_value; 431 } 432 433 return '[ ' . join( ', ', $t_result ) . ' ]'; 434 } 435 436 # -------------------- 437 # PROTECTED function to print graph attributes and defaults. 438 function _print_graph_defaults() { 439 foreach ( $this->attributes as $t_name => $t_value ) { 440 if ( !ereg( "[a-zA-Z]+", $t_name ) ) 441 continue; 442 443 if ( is_string( $t_value ) ) 444 $t_value = '"' . addcslashes( $t_value, "\0..\37\"\\") . '"'; 445 else if ( is_integer( $t_value ) or is_float( $t_value ) ) 446 $t_value = (string) $t_value; 447 else 448 continue; 449 450 echo "\t" . $t_name . '=' . $t_value . ";\n"; 451 } 452 453 if ( null !== $this->default_node ) { 454 $t_attr = $this->_build_attribute_list( $this->default_node ); 455 echo "\t" . 'node ' . $t_attr . ";\n"; 456 } 457 458 if ( null !== $this->default_edge ) { 459 $t_attr = $this->_build_attribute_list( $this->default_edge ); 460 echo "\t" . 'edge ' . $t_attr . ";\n"; 461 } 462 } 463 } 464 465 # -------------------- 466 # Directed graph creation and manipulation. 467 class Digraph extends Graph { 468 # -------------------- 469 # Constructor for Digraph objects. 470 function Digraph( $p_name = 'G', $p_attributes = array(), $p_tool = 'dot', 471 $p_com_module = 'WinGraphviz.DOT' ) { 472 parent::Graph( $p_name, $p_attributes, $p_tool, $p_com_module ); 473 } 474 475 # -------------------- 476 # Generates a directed graph representation (suitable for dot). 477 function generate() { 478 echo 'digraph ' . $this->name . ' {' . "\n"; 479 480 $this->_print_graph_defaults(); 481 482 foreach ( $this->nodes as $t_name => $t_attr ) { 483 $t_name = '"' . addcslashes( $t_name, "\0..\37\"\\") . '"'; 484 $t_attr = $this->_build_attribute_list( $t_attr ); 485 echo "\t" . $t_name . ' ' . $t_attr . ";\n"; 486 } 487 488 foreach ( $this->edges as $t_edge ) { 489 $t_src = '"' . addcslashes( $t_edge['src'], "\0..\37\"\\") . '"'; 490 $t_dst = '"' . addcslashes( $t_edge['dst'], "\0..\37\"\\") . '"'; 491 $t_attr = $t_edge['attributes']; 492 $t_attr = $this->_build_attribute_list( $t_attr ); 493 echo "\t" . $t_src . ' -> ' . $t_dst . ' ' . $t_attr . ";\n"; 494 } 495 496 echo "};\n"; 497 } 498 } 499 500 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 09:42:17 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |