[ 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/ -> relationship_graph_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: relationship_graph_api.php,v 1.6.2.1 2007-10-13 22:35:42 giallu Exp $
  22      # --------------------------------------------------------
  23  
  24      ### Relationship Graph API ###
  25  
  26      $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
  27  
  28      require_once ( $t_core_dir . 'relationship_api.php' );
  29      require_once ( $t_core_dir . 'graphviz_api.php' );
  30  
  31      # ================================================================
  32      # Author: Juliano Ravasi Ferraz <jferraz at users sourceforge net>
  33      # ================================================================
  34      #
  35      # This uses GraphViz utilities to generate relationship graphs for
  36      # issues. Either GraphViz (for all OSs except Windows) or
  37      # WinGraphviz (for Windows) must be installed in order to use this
  38      # feature.
  39      #
  40      # Graphviz is available at:
  41      #  - http://www.graphviz.org/
  42      #  - http://www.research.att.com/sw/tools/graphviz/
  43      #
  44      # WinGraphviz is available at:
  45      #  - http://home.so-net.net.tw/oodtsen/wingraphviz/
  46      #
  47      # Most Linux distributions already have a GraphViz package
  48      # conveniently available for download and install. Refer to
  49      # config_defaults_inc.php for how to enable this feature once
  50      # GraphViz is installed.
  51  
  52      # --------------------
  53      # Generate a relationship graph for the given issue.
  54  	function relgraph_generate_rel_graph( $p_bug_id, $p_bug = null ) {
  55  
  56          # List of visited issues and their data.
  57          $v_bug_list = array ( );
  58          $v_rel_list = array ( );
  59  
  60          # Queue for breadth-first
  61          $v_queue = array ( );
  62  
  63          # Now we visit all related issues.
  64          $t_max_depth        = config_get( 'relationship_graph_max_depth' );
  65  
  66          # Put the first element into queue.
  67          array_push( $v_queue, array ( 0, $p_bug_id ) );
  68  
  69          # And now we proccess it
  70          while ( !empty( $v_queue ) ) {
  71              list( $t_depth, $t_id ) = array_shift( $v_queue );
  72  
  73              if ( isset( $v_bug_list[$t_id] ) )
  74                  continue;
  75  
  76              if ( !bug_exists( $t_id ) )
  77                  continue;
  78  
  79              if ( !access_has_bug_level( VIEWER, $t_id ) )
  80                  continue;
  81  
  82              $v_bug_list[$t_id] = bug_prepare_display( bug_get( $t_id, false ) );
  83  
  84              $t_relationships    = relationship_get_all_src( $t_id );
  85              foreach ( $t_relationships as $t_relationship ) {
  86                  $t_dst = $t_relationship->dest_bug_id;
  87                  if ( BUG_DEPENDANT == $t_relationship->type ) {
  88                      $v_rel_list[$t_id][$t_dst] = BUG_DEPENDANT;
  89                      $v_rel_list[$t_dst][$t_id] = BUG_BLOCKS;
  90                  } else {
  91                      $v_rel_list[$t_id][$t_dst] = $t_relationship->type;
  92                      $v_rel_list[$t_dst][$t_id] = $t_relationship->type;
  93                  }
  94  
  95                  if ( $t_depth < $t_max_depth )
  96                      array_push( $v_queue, array ( $t_depth + 1, $t_dst ) );
  97              }
  98  
  99              $t_relationships    = relationship_get_all_dest( $t_id );
 100              foreach ( $t_relationships as $t_relationship ) {
 101                  $t_dst = $t_relationship->src_bug_id;
 102                  if ( BUG_DEPENDANT == $t_relationship->type ) {
 103                      $v_rel_list[$t_id][$t_dst] = BUG_BLOCKS;
 104                      $v_rel_list[$t_dst][$t_id] = BUG_DEPENDANT;
 105                  } else {
 106                      $v_rel_list[$t_id][$t_dst] = $t_relationship->type;
 107                      $v_rel_list[$t_dst][$t_id] = $t_relationship->type;
 108                  }
 109  
 110                  if ( $t_depth < $t_max_depth )
 111                      array_push( $v_queue, array ( $t_depth + 1, $t_dst ) );
 112              }
 113          }
 114  
 115          # We have already collected all the information we need to generate
 116          # the graph. Now it is the matter to create a Digraph object and
 117          # store the information there, along with graph formatting attributes.
 118          $t_id_string        = bug_format_id( $p_bug_id );
 119          $t_graph_fontname    = config_get( 'relationship_graph_fontname' );
 120          $t_graph_fontsize    = config_get( 'relationship_graph_fontsize' );
 121          $t_graph_fontpath    = config_get( 'system_font_folder' );
 122          $t_view_on_click    = config_get( 'relationship_graph_view_on_click' );
 123          $t_neato_tool        = config_get( 'neato_tool' );
 124  
 125          $t_graph_attributes    = array ( );
 126  
 127          if ( !empty( $t_graph_fontpath ) )
 128              $t_graph_attributes['fontpath'] = $t_graph_fontpath;
 129  
 130          $t_graph = new Graph( $t_id_string, $t_graph_attributes, $t_neato_tool );
 131  
 132          $t_graph->set_default_node_attr( array (
 133              'fontname'    => $t_graph_fontname,
 134              'fontsize'    => $t_graph_fontsize,
 135              'shape'        => 'record',
 136              'style'        => 'filled',
 137              'height'    => '0.2',
 138              'width'        => '0.4'
 139          ) );
 140  
 141          $t_graph->set_default_edge_attr( array (
 142              'style'        => 'solid',
 143              'color'        => '#0000C0',
 144              'dir'        => 'none'
 145          ) );
 146  
 147          # Add all issue nodes and edges to the graph.
 148          ksort( $v_bug_list );
 149          foreach ( $v_bug_list as $t_id => $t_bug ) {
 150              $t_id_string    = bug_format_id( $t_id );
 151  
 152              if ( $t_view_on_click )
 153                  $t_url = string_get_bug_view_url( $t_id );
 154              else
 155                  $t_url = 'bug_relationship_graph.php?bug_id=' . $t_id . '&amp;graph=relation';
 156  
 157              relgraph_add_bug_to_graph( $t_graph, $t_id_string, $t_bug,
 158                                         $t_url, $t_id == $p_bug_id );
 159  
 160              # Now add all relationship edges to the graph.
 161              if ( isset( $v_rel_list[$t_id] ) ) {
 162                  foreach ( $v_rel_list[$t_id] as $t_dst => $t_relation ) {
 163                      # Do not create edges for unvisited bugs.
 164                      if ( !isset( $v_bug_list[$t_dst] ) )
 165                          continue;
 166  
 167                      # avoid double links
 168                      if ( $t_dst < $t_id )
 169                          continue;
 170  
 171                      $t_related_id    = bug_format_id( $t_dst );
 172  
 173            global $g_relationships;
 174            if ( isset( $g_relationships[ $t_relation ] ) && isset( $g_relationships[ $t_relation ][ '#edge_style' ] ) ) {
 175              $t_edge_style = $g_relationships[ $t_relation ][ '#edge_style' ];
 176            } else {
 177              $t_edge_style = array ( );
 178            }
 179  
 180                      $t_graph->add_edge( $t_id_string, $t_related_id, $t_edge_style );
 181                  }
 182              }
 183          }
 184  
 185          return $t_graph;
 186      }
 187  
 188  
 189      # --------------------
 190      # Generate a dependency relationship graph for the given issue.
 191  	function relgraph_generate_dep_graph( $p_bug_id, $p_bug = null, $p_horizontal = false ) {
 192  
 193          # List of visited issues and their data.
 194          $v_bug_list = array ( );
 195  
 196          # Firstly, we visit all ascendant issues and all descendant issues
 197          # and collect all the necessary data in the $v_bug_list variable.
 198          # We do not visit other descendants of our parents, neither other
 199          # ascendants of our children, to avoid displaying too much unrelated
 200          # issues. We still collect the information about those relationships,
 201          # so, if these issues happen to be visited also, relationship links
 202          # will be preserved.
 203  
 204          # The first issue in the list is the one we are parting from.
 205          if ( null === $p_bug )
 206              $p_bug = bug_prepare_display( bug_get( $p_bug_id, true ) );
 207  
 208          $v_bug_list[$p_bug_id] = $p_bug;
 209          $v_bug_list[$p_bug_id]->is_descendant = true;
 210          $v_bug_list[$p_bug_id]->parents = array ( );
 211          $v_bug_list[$p_bug_id]->children = array ( );
 212  
 213          # Now we visit all ascendants of the root issue.
 214          $t_relationships = relationship_get_all_dest( $p_bug_id );
 215          foreach ( $t_relationships as $t_relationship ) {
 216              if ( $t_relationship->type != BUG_DEPENDANT )
 217                  continue;
 218  
 219              $v_bug_list[$p_bug_id]->parents[] = $t_relationship->src_bug_id;
 220              relgraph_add_parent( $v_bug_list, $t_relationship->src_bug_id );
 221          }
 222  
 223          $t_relationships = relationship_get_all_src( $p_bug_id );
 224          foreach ( $t_relationships as $t_relationship ) {
 225              if ( $t_relationship->type != BUG_DEPENDANT )
 226                  continue;
 227  
 228              $v_bug_list[$p_bug_id]->children[] = $t_relationship->dest_bug_id;
 229              relgraph_add_child( $v_bug_list, $t_relationship->dest_bug_id );
 230          }
 231  
 232          # We have already collected all the information we need to generate
 233          # the graph. Now it is the matter to create a Digraph object and
 234          # store the information there, along with graph formatting attributes.
 235          $t_id_string        = bug_format_id( $p_bug_id );
 236          $t_graph_fontname    = config_get( 'relationship_graph_fontname' );
 237          $t_graph_fontsize    = config_get( 'relationship_graph_fontsize' );
 238          $t_graph_fontpath    = config_get( 'system_font_folder' );
 239          $t_view_on_click    = config_get( 'relationship_graph_view_on_click' );
 240          $t_dot_tool            = config_get( 'dot_tool' );
 241  
 242          $t_graph_attributes    = array ( );
 243  
 244          if ( !empty( $t_graph_fontpath ) )
 245              $t_graph_attributes['fontpath'] = $t_graph_fontpath;
 246  
 247          if ( $p_horizontal ) {
 248              $t_graph_attributes['rankdir'] = 'LR';
 249              $t_graph_orientation = 'horizontal';
 250          } else {
 251              $t_graph_orientation = 'vertical';
 252          }
 253  
 254          $t_graph = new Digraph( $t_id_string, $t_graph_attributes, $t_dot_tool );
 255  
 256          $t_graph->set_default_node_attr( array (
 257              'fontname'    => $t_graph_fontname,
 258              'fontsize'    => $t_graph_fontsize,
 259              'shape'        => 'record',
 260              'style'        => 'filled',
 261              'height'    => '0.2',
 262              'width'        => '0.4'
 263          ) );
 264  
 265          $t_graph->set_default_edge_attr( array (
 266              'style'        => 'solid',
 267              'color'        => '#C00000',
 268              'dir'        => 'back'
 269          ) );
 270  
 271          # Add all issue nodes and edges to the graph.
 272          foreach ( $v_bug_list as $t_related_bug_id => $t_related_bug ) {
 273              $t_id_string    = bug_format_id( $t_related_bug_id );
 274  
 275              if ( $t_view_on_click )
 276                  $t_url = string_get_bug_view_url( $t_related_bug_id );
 277              else
 278                  $t_url = 'bug_relationship_graph.php?bug_id=' . $t_related_bug_id . '&amp;graph=dependency&orientation=' . $t_graph_orientation;
 279  
 280              relgraph_add_bug_to_graph( $t_graph, $t_id_string, $t_related_bug,
 281                                         $t_url, $t_related_bug_id == $p_bug_id );
 282  
 283              # Now add all relationship edges to the graph.
 284              foreach ( $v_bug_list[$t_related_bug_id]->parents as $t_parent_id ) {
 285                  # Do not create edges for unvisited bugs.
 286                  if ( !isset( $v_bug_list[$t_parent_id] ) )
 287                      continue;
 288  
 289                  $t_parent_node    = bug_format_id( $t_parent_id );
 290                  $t_graph->add_edge( $t_parent_node, $t_id_string );
 291              }
 292          }
 293  
 294          return $t_graph;
 295      }
 296  
 297  
 298      # --------------------
 299      # Internal function used to visit ascendant issues recursively.
 300  	function relgraph_add_parent( &$p_bug_list, $p_bug_id ) {
 301  
 302          # If the issue is already in the list, we already visited it, just
 303          # leave.
 304          if ( isset( $p_bug_list[$p_bug_id] ) )
 305              return true;
 306  
 307          # Check if the issue really exists and we have access to it. If not,
 308          # it is like it didn't exist.
 309          if ( !bug_exists( $p_bug_id ) )
 310              return false;
 311  
 312          if ( !access_has_bug_level( VIEWER, $p_bug_id ) )
 313              return false;
 314  
 315          # Add the issue to the list.
 316          $p_bug_list[$p_bug_id] = bug_prepare_display( bug_get( $p_bug_id, false ) );
 317          $p_bug_list[$p_bug_id]->is_descendant = false;
 318          $p_bug_list[$p_bug_id]->parents = array ( );
 319          $p_bug_list[$p_bug_id]->children = array ( );
 320  
 321          # Add all parent issues to the list of parents and visit them
 322          # recursively.
 323          $t_relationships = relationship_get_all_dest( $p_bug_id );
 324          foreach ( $t_relationships as $t_relationship ) {
 325              if ( $t_relationship->type != BUG_DEPENDANT )
 326                  continue;
 327  
 328              $p_bug_list[$p_bug_id]->parents[] = $t_relationship->src_bug_id;
 329              relgraph_add_parent( $p_bug_list, $t_relationship->src_bug_id );
 330          }
 331  
 332          # Add all child issues to the list of children. Do not visit them
 333          # since this will add too much data that is unrelated to the original
 334          # issue, and has a potential to generate really huge graphs.
 335          $t_relationships = relationship_get_all_src( $p_bug_id );
 336          foreach ( $t_relationships as $t_relationship ) {
 337              if ( $t_relationship->type != BUG_DEPENDANT )
 338                  continue;
 339  
 340              $p_bug_list[$p_bug_id]->children[] = $t_relationship->dest_bug_id;
 341          }
 342  
 343          return true;
 344      }
 345  
 346  
 347      # --------------------
 348      # Internal function used to visit descendant issues recursively.
 349  	function relgraph_add_child( &$p_bug_list, $p_bug_id ) {
 350  
 351          # Check if the issue is already in the issue list.
 352          if ( isset( $p_bug_list[$p_bug_id] ) ) {
 353  
 354              # The issue is in the list, but we cannot discard it since it
 355              # may be a parent issue (whose children were not visited).
 356  
 357              if ( !$p_bug_list[$p_bug_id]->is_descendant ) {
 358                  # Yes, we visited this issue as a parent... This is the case
 359                  # where someone set up a cyclic relationship (I really hope
 360                  # nobody ever do this, but should keep sanity) for this
 361                  # issue. We just have to finish the job, visiting all issues
 362                  # that were already listed by _add_parent().
 363                  $p_bug_list[$p_bug_id]->is_descendant = true;
 364  
 365                  foreach ( $p_bug_list[$p_bug_id]->children as $t_child )
 366                      relgraph_add_child( $p_bug_id, $t_child );
 367              }
 368          } else {
 369              # The issue is not in the list, proceed as usual.
 370  
 371              # Check if the issue really exists and we have access to it.
 372              # If not, it is like it didn't exist.
 373              if ( !bug_exists( $p_bug_id ) )
 374                  return false;
 375  
 376              if ( !access_has_bug_level( VIEWER, $p_bug_id ) )
 377                  return false;
 378  
 379              # Add the issue to the list.
 380              $p_bug_list[$p_bug_id] = bug_prepare_display( bug_get( $p_bug_id, false ) );
 381              $p_bug_list[$p_bug_id]->is_descendant = true;
 382              $p_bug_list[$p_bug_id]->parents = array ( );
 383              $p_bug_list[$p_bug_id]->children = array ( );
 384  
 385              # Add all parent issues to the list of parents. Do not visit them
 386              # for the same reason we didn't visit the children of all
 387              # ancestors.
 388              $t_relationships = relationship_get_all_dest( $p_bug_id );
 389              foreach ( $t_relationships as $t_relationship ) {
 390                  if ( $t_relationship->type != BUG_DEPENDANT )
 391                      continue;
 392  
 393                  $p_bug_list[$p_bug_id]->parents[] = $t_relationship->src_bug_id;
 394              }
 395  
 396              # Add all child issues to the list of children and visit them
 397              # recursively.
 398              $t_relationships = relationship_get_all_src( $p_bug_id );
 399              foreach ( $t_relationships as $t_relationship ) {
 400                  if ( $t_relationship->type != BUG_DEPENDANT )
 401                      continue;
 402  
 403                  $p_bug_list[$p_bug_id]->children[] = $t_relationship->dest_bug_id;
 404                  relgraph_add_child( $p_bug_list, $t_relationship->dest_bug_id );
 405              }
 406          }
 407  
 408          return true;
 409      }
 410  
 411  
 412      # --------------------
 413      # Outputs a png image for the given relationship graph, previously
 414      # generated by relgraph_generate_graph_for_bug().
 415  	function relgraph_output_image( $p_graph ) {
 416          $p_graph->output( 'png', true );
 417      }
 418  
 419  
 420      # --------------------
 421      # Outputs an image map in HTML form (too bad dot didn't output XHTML...)
 422      # for the given relationship graph, previously generated by
 423      # relgraph_generate_graph_for_bug().
 424  	function relgraph_output_map( $p_graph, $p_name ) {
 425          echo '<map name="' . $p_name . '">' . "\n";
 426          $p_graph->output( 'cmap' );
 427          echo '</map>' . "\n";
 428      }
 429  
 430  
 431      # --------------------
 432      # Internal function used to add a bug to the given graph.
 433  	function relgraph_add_bug_to_graph( &$p_graph, $p_bug_id, $p_bug, $p_url = null, $p_highlight = false ) {
 434          $t_node_attributes = array ( );
 435          $t_node_attributes['label']        = $p_bug_id;
 436  
 437          if ( $p_highlight ) {
 438              $t_node_attributes['color'] = '#0000FF';
 439              $t_node_attributes['style'] = 'bold, filled';
 440          } else {
 441              $t_node_attributes['color'] = 'black';
 442              $t_node_attributes['style'] = 'filled';
 443          }
 444  
 445          $t_node_attributes['fillcolor']    = get_status_color( $p_bug->status );
 446  
 447          if ( null !== $p_url )
 448              $t_node_attributes['URL']    = $p_url;
 449  
 450          $t_summary        = $p_bug->summary;
 451          $t_status        = get_enum_element( 'status', $p_bug->status );
 452          $t_node_attributes['tooltip']    = '[' . $t_status . '] ' . $t_summary;
 453  
 454          $p_graph->add_node( $p_bug_id, $t_node_attributes );
 455      }
 456  
 457  ?>


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