showdependencytree.cgi 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/usr/bin/env perl -wT
  2. # -*- Mode: perl; indent-tabs-mode: nil -*-
  3. #
  4. # The contents of this file are subject to the Mozilla Public
  5. # License Version 1.1 (the "License"); you may not use this file
  6. # except in compliance with the License. You may obtain a copy of
  7. # the License at http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS
  10. # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11. # implied. See the License for the specific language governing
  12. # rights and limitations under the License.
  13. #
  14. # The Original Code is the Bugzilla Bug Tracking System.
  15. #
  16. # The Initial Developer of the Original Code is Netscape Communications
  17. # Corporation. Portions created by Netscape are
  18. # Copyright (C) 1998 Netscape Communications Corporation. All
  19. # Rights Reserved.
  20. #
  21. # Contributor(s): Terry Weissman <terry@mozilla.org>
  22. # Andreas Franke <afranke@mathweb.org>
  23. # Christian Reis <kiko@async.com.br>
  24. # Myk Melez <myk@mozilla.org>
  25. # Frédéric Buclin <LpSolit@gmail.com>
  26. use strict;
  27. use lib qw(. lib);
  28. use Bugzilla;
  29. use Bugzilla::Error;
  30. use Bugzilla::Bug;
  31. use List::Util qw(max);
  32. my $user = Bugzilla->login();
  33. my $cgi = Bugzilla->cgi;
  34. my $template = Bugzilla->template;
  35. my $vars = {};
  36. # Connect to the shadow database if this installation is using one to improve
  37. # performance.
  38. my $dbh = Bugzilla->switch_to_shadow_db();
  39. ################################################################################
  40. # Data/Security Validation #
  41. ################################################################################
  42. # Make sure the bug ID is a positive integer representing an existing
  43. # bug that the user is authorized to access.
  44. my $id = $cgi->param('id') || ThrowUserError('improper_bug_id_field_value');
  45. ValidateBugID($id);
  46. my $current_bug = new Bugzilla::Bug($id);
  47. local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0;
  48. local our $maxdepth = $cgi->param('maxdepth') || 0;
  49. if ($maxdepth !~ /^\d+$/) { $maxdepth = 0 };
  50. ################################################################################
  51. # Main Section #
  52. ################################################################################
  53. # Stores the greatest depth to which either tree goes.
  54. local our $realdepth = 0;
  55. # Generate the tree of bugs that this bug depends on and a list of IDs
  56. # appearing in the tree.
  57. my $dependson_tree = { $id => $current_bug };
  58. my $dependson_ids = {};
  59. GenerateTree($id, "dependson", 1, $dependson_tree, $dependson_ids);
  60. $vars->{'dependson_tree'} = $dependson_tree;
  61. $vars->{'dependson_ids'} = [keys(%$dependson_ids)];
  62. # Generate the tree of bugs that this bug blocks and a list of IDs
  63. # appearing in the tree.
  64. my $blocked_tree = { $id => $current_bug };
  65. my $blocked_ids = {};
  66. GenerateTree($id, "blocked", 1, $blocked_tree, $blocked_ids);
  67. $vars->{'blocked_tree'} = $blocked_tree;
  68. $vars->{'blocked_ids'} = [keys(%$blocked_ids)];
  69. $vars->{'realdepth'} = $realdepth;
  70. $vars->{'bugid'} = $id;
  71. $vars->{'maxdepth'} = $maxdepth;
  72. $vars->{'hide_resolved'} = $hide_resolved;
  73. print $cgi->header();
  74. $template->process("bug/dependency-tree.html.tmpl", $vars)
  75. || ThrowTemplateError($template->error());
  76. ################################################################################
  77. # Recursive Tree Generation Function #
  78. ################################################################################
  79. sub GenerateTree {
  80. # Generates a dependency tree for a given bug. Calls itself recursively
  81. # to generate sub-trees for the bug's dependencies.
  82. my ($bug_id, $relationship, $depth, $bugs, $ids) = @_;
  83. my @dependencies;
  84. if ($relationship eq 'dependson') {
  85. @dependencies = @{$bugs->{$bug_id}->dependson};
  86. }
  87. else {
  88. @dependencies = @{$bugs->{$bug_id}->blocked};
  89. }
  90. # Don't do anything if this bug doesn't have any dependencies.
  91. return unless scalar(@dependencies);
  92. # Record this depth in the global $realdepth variable if it's farther
  93. # than we've gone before.
  94. $realdepth = max($realdepth, $depth);
  95. foreach my $dep_id (@dependencies) {
  96. # Get this dependency's record from the database and generate
  97. # its sub-tree if we haven't already done so (which happens
  98. # when bugs appear in dependency trees multiple times).
  99. if (!$bugs->{$dep_id}) {
  100. $bugs->{$dep_id} = new Bugzilla::Bug($dep_id);
  101. GenerateTree($dep_id, $relationship, $depth+1, $bugs, $ids);
  102. }
  103. # Add this dependency to the list of this bug's dependencies
  104. # if it exists, if we haven't exceeded the maximum depth the user
  105. # wants the tree to go, and if the dependency isn't resolved
  106. # (if we're ignoring resolved dependencies).
  107. if (!$bugs->{$dep_id}->{'error'}
  108. && Bugzilla->user->can_see_bug($dep_id)
  109. && (!$maxdepth || $depth <= $maxdepth)
  110. && ($bugs->{$dep_id}->isopened || !$hide_resolved))
  111. {
  112. # Due to AUTOLOAD in Bug.pm, we cannot add 'dependencies'
  113. # as a bug object attribute from here.
  114. push(@{$bugs->{'dependencies'}->{$bug_id}}, $dep_id);
  115. $ids->{$dep_id} = 1;
  116. }
  117. }
  118. }