1 #!/usr/bin/env perl -wT
2 # -*- Mode: perl; indent-tabs-mode: nil -*-
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/
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.
14 # The Original Code is the Bugzilla Bug Tracking System.
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
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>
35 use List
::Util
qw(max);
37 my $user = Bugzilla
->login();
39 my $cgi = Bugzilla
->cgi;
40 my $template = Bugzilla
->template;
42 # Connect to the shadow database if this installation is using one to improve
44 my $dbh = Bugzilla
->switch_to_shadow_db();
46 ################################################################################
47 # Data/Security Validation #
48 ################################################################################
50 # Make sure the bug ID is a positive integer representing an existing
51 # bug that the user is authorized to access.
52 my $id = $cgi->param('id') || ThrowUserError
('improper_bug_id_field_value');
54 my $current_bug = new Bugzilla
::Bug
($id);
56 local our $hide_resolved = $cgi->param('hide_resolved') ?
1 : 0;
58 local our $maxdepth = $cgi->param('maxdepth') || 0;
59 if ($maxdepth !~ /^\d+$/) { $maxdepth = 0 };
61 ################################################################################
63 ################################################################################
65 # Stores the greatest depth to which either tree goes.
66 local our $realdepth = 0;
68 # Generate the tree of bugs that this bug depends on and a list of IDs
69 # appearing in the tree.
70 my $dependson_tree = { $id => $current_bug };
71 my $dependson_ids = {};
72 GenerateTree
($id, "dependson", 1, $dependson_tree, $dependson_ids);
73 $vars->{'dependson_tree'} = $dependson_tree;
74 $vars->{'dependson_ids'} = [keys(%$dependson_ids)];
76 # Generate the tree of bugs that this bug blocks and a list of IDs
77 # appearing in the tree.
78 my $blocked_tree = { $id => $current_bug };
80 GenerateTree
($id, "blocked", 1, $blocked_tree, $blocked_ids);
81 $vars->{'blocked_tree'} = $blocked_tree;
82 $vars->{'blocked_ids'} = [keys(%$blocked_ids)];
84 $vars->{'realdepth'} = $realdepth;
86 $vars->{'bugid'} = $id;
87 $vars->{'maxdepth'} = $maxdepth;
88 $vars->{'hide_resolved'} = $hide_resolved;
91 $template->process("bug/dependency-tree.html.tmpl", $vars)
92 || ThrowTemplateError
($template->error());
94 ################################################################################
95 # Recursive Tree Generation Function #
96 ################################################################################
99 # Generates a dependency tree for a given bug. Calls itself recursively
100 # to generate sub-trees for the bug's dependencies.
101 my ($bug_id, $relationship, $depth, $bugs, $ids) = @_;
104 if ($relationship eq 'dependson') {
105 @dependencies = @
{$bugs->{$bug_id}->dependson};
108 @dependencies = @
{$bugs->{$bug_id}->blocked};
111 # Don't do anything if this bug doesn't have any dependencies.
112 return unless scalar(@dependencies);
114 # Record this depth in the global $realdepth variable if it's farther
115 # than we've gone before.
116 $realdepth = max
($realdepth, $depth);
118 foreach my $dep_id (@dependencies) {
119 # Get this dependency's record from the database and generate
120 # its sub-tree if we haven't already done so (which happens
121 # when bugs appear in dependency trees multiple times).
122 if (!$bugs->{$dep_id}) {
123 $bugs->{$dep_id} = new Bugzilla
::Bug
($dep_id);
124 GenerateTree
($dep_id, $relationship, $depth+1, $bugs, $ids);
127 # Add this dependency to the list of this bug's dependencies
128 # if it exists, if we haven't exceeded the maximum depth the user
129 # wants the tree to go, and if the dependency isn't resolved
130 # (if we're ignoring resolved dependencies).
131 if (!$bugs->{$dep_id}->{'error'}
132 && Bugzilla
->user->can_see_bug($dep_id)
133 && (!$maxdepth || $depth <= $maxdepth)
134 && ($bugs->{$dep_id}->isopened || !$hide_resolved))
136 # Due to AUTOLOAD in Bug.pm, we cannot add 'dependencies'
137 # as a bug object attribute from here.
138 push(@
{$bugs->{'dependencies'}->{$bug_id}}, $dep_id);