You need to sign in or sign up before continuing.
showdependencytree.cgi 4.5 KB
Newer Older
1
#!/usr/bin/perl -T
2 3 4
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
#
6 7
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
8

9
use 5.10.1;
10
use strict;
11 12
use warnings;

13
use lib qw(. lib);
14

15
use Bugzilla;
16
use Bugzilla::Error;
17
use Bugzilla::Bug;
18

19 20
use List::Util qw(max);

21
my $user = Bugzilla->login();
22

23
my $cgi      = Bugzilla->cgi;
24
my $template = Bugzilla->template;
25 26
my $vars     = {};

27 28
# Connect to the shadow database if this installation is using one to improve
# performance.
29
my $dbh = Bugzilla->switch_to_shadow_db();
30

31 32 33
################################################################################
# Data/Security Validation                                                     #
################################################################################
34 35

# Make sure the bug ID is a positive integer representing an existing
36
# bug that the user is authorized to access.
37
my $bug = Bugzilla::Bug->check(scalar $cgi->param('id'));
38
my $id  = $bug->id;
39

40 41
local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0;
local our $maxdepth = $cgi->param('maxdepth') || 0;
42
if ($maxdepth !~ /^\d+$/) {
43
  $maxdepth = 0;
44
}
45

46 47 48
################################################################################
# Main Section                                                                 #
################################################################################
49

50
# Stores the greatest depth to which either tree goes.
51
local our $realdepth = 0;
52

53 54
# Generate the tree of bugs that this bug depends on and a list of IDs
# appearing in the tree.
55
my $dependson_tree = {$id => $bug};
56
my $dependson_ids  = {};
57 58
GenerateTree($id, "dependson", 1, $dependson_tree, $dependson_ids);
$vars->{'dependson_tree'} = $dependson_tree;
59
$vars->{'dependson_ids'}  = [keys(%$dependson_ids)];
60 61 62

# Generate the tree of bugs that this bug blocks and a list of IDs
# appearing in the tree.
63
my $blocked_tree = {$id => $bug};
64
my $blocked_ids  = {};
65 66
GenerateTree($id, "blocked", 1, $blocked_tree, $blocked_ids);
$vars->{'blocked_tree'} = $blocked_tree;
67
$vars->{'blocked_ids'}  = [keys(%$blocked_ids)];
68

69 70 71 72
$vars->{'bugid'}         = $id;
$vars->{'realdepth'}     = $realdepth;
$vars->{'maxdepth'}      = $maxdepth;
$vars->{'hide_resolved'} = $hide_resolved;
73

74
print $cgi->header();
75 76
$template->process("bug/dependency-tree.html.tmpl", $vars)
  || ThrowTemplateError($template->error());
77

78
# Tree Generation Functions
79 80

sub GenerateTree {
81 82 83 84 85 86 87 88 89 90 91
  my ($bug_id, $relationship, $depth, $bugs, $ids) = @_;

  # determine just the list of bug ids
  _generate_bug_ids($bug_id, $relationship, $depth, $ids);
  my $bug_ids = [keys %$ids];
  return unless @$bug_ids;

  # load all the bugs at once
  foreach my $bug (@{Bugzilla::Bug->new_from_list($bug_ids)}) {
    if (!$bug->{error}) {
      $bugs->{$bug->id} = $bug;
92
    }
93
  }
94

95 96
  # preload bug visibility
  Bugzilla->user->visible_bugs($bug_ids);
97

98 99
  # and generate the tree
  _generate_tree($bug_id, $relationship, $depth, $bugs, $ids);
100 101 102
}

sub _generate_bug_ids {
103 104 105 106 107 108 109 110 111 112 113
  my ($bug_id, $relationship, $depth, $ids) = @_;

  # Record this depth in the global $realdepth variable if it's farther
  # than we've gone before.
  $realdepth = max($realdepth, $depth);

  my $dependencies = _get_dependencies($bug_id, $relationship);
  foreach my $dep_id (@$dependencies) {
    if (!$maxdepth || $depth <= $maxdepth) {
      $ids->{$dep_id} = 1;
      _generate_bug_ids($dep_id, $relationship, $depth + 1, $ids);
114
    }
115
  }
116 117 118
}

sub _generate_tree {
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
  my ($bug_id, $relationship, $depth, $bugs, $ids) = @_;

  my $dependencies = _get_dependencies($bug_id, $relationship);

  foreach my $dep_id (@$dependencies) {

    # recurse
    if (!$maxdepth || $depth < $maxdepth) {
      _generate_tree($dep_id, $relationship, $depth + 1, $bugs, $ids);
    }

    # remove bugs according to visiblity
    if (!Bugzilla->user->can_see_bug($dep_id)) {
      delete $ids->{$dep_id};
    }
    elsif (!grep { $_ == $dep_id } @{$bugs->{dependencies}->{$bug_id}}) {
      push @{$bugs->{dependencies}->{$bug_id}}, $dep_id;
136
    }
137
  }
138
}
139 140

sub _get_dependencies {
141 142 143 144 145 146 147 148
  my ($bug_id, $relationship) = @_;
  my $cache = Bugzilla->request_cache->{dependency_cache} ||= {};
  return $cache->{$bug_id}->{$relationship}
    ||= $relationship eq 'dependson'
    ? Bugzilla::Bug::EmitDependList('blocked', 'dependson', $bug_id,
    $hide_resolved)
    : Bugzilla::Bug::EmitDependList('dependson', 'blocked', $bug_id,
    $hide_resolved);
149 150
}