[ Index ]
 

Code source de Mantis 1.1.0rc3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/core/ -> graphviz_api.php (source)

   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  ?>


Généré le : Thu Nov 29 09:42:17 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics