You need to sign in or sign up before continuing.
showdependencytree.cgi 4.61 KB
Newer Older
1
#!/usr/bin/perl -wT
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 10

use strict;

11
use lib qw(. lib);
12

13
use Bugzilla;
14
use Bugzilla::Error;
15
use Bugzilla::Bug;
16

17 18
use List::Util qw(max);

19
my $user = Bugzilla->login();
20

21
my $cgi = Bugzilla->cgi;
22 23
my $template = Bugzilla->template;
my $vars = {};
24 25
# Connect to the shadow database if this installation is using one to improve
# performance.
26
my $dbh = Bugzilla->switch_to_shadow_db();
27

28 29 30
################################################################################
# Data/Security Validation                                                     #
################################################################################
31 32

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

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

43 44 45
################################################################################
# Main Section                                                                 #
################################################################################
46

47
# Stores the greatest depth to which either tree goes.
48
local our $realdepth = 0;
49

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

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

66 67 68 69
$vars->{'bugid'}         = $id;
$vars->{'realdepth'}     = $realdepth;
$vars->{'maxdepth'}      = $maxdepth;
$vars->{'hide_resolved'} = $hide_resolved;
70

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

75
# Tree Generation Functions
76 77 78

sub GenerateTree {
    my ($bug_id, $relationship, $depth, $bugs, $ids) = @_;
79

80 81 82 83 84 85 86 87 88 89
    # 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;
        }
90 91
    }

92 93 94 95 96 97 98 99 100
    # preload bug visibility
    Bugzilla->user->visible_bugs($bug_ids);

    # and generate the tree
    _generate_tree($bug_id, $relationship, $depth, $bugs, $ids);
}

sub _generate_bug_ids {
    my ($bug_id, $relationship, $depth, $ids) = @_;
101

102
    # Record this depth in the global $realdepth variable if it's farther
103 104
    # than we've gone before.
    $realdepth = max($realdepth, $depth);
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

    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);
        }
    }
}

sub _generate_tree {
    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);
124
        }
125

126 127
        # remove bugs according to visiblity
        if (!Bugzilla->user->can_see_bug($dep_id)) {
128 129 130 131
            delete $ids->{$dep_id};
        }
        elsif (!grep { $_ == $dep_id } @{ $bugs->{dependencies}->{$bug_id} }) {
            push @{ $bugs->{dependencies}->{$bug_id} }, $dep_id;
132 133 134
        }
    }
}
135 136 137 138 139 140

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