blob: 8193d92b961f6ba604175a0efc8dd5fd48d01a6d [file] [log] [blame]
ddkilzer@apple.comf573e632009-07-03 02:14:39 +00001#!/usr/bin/env perl -wT
timothy@apple.comf42518d2008-02-06 20:19:16 +00002# -*- 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>
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000025# Frédéric Buclin <LpSolit@gmail.com>
timothy@apple.comf42518d2008-02-06 20:19:16 +000026
27use strict;
28
ddkilzer@apple.com097da082009-07-03 02:14:25 +000029use lib qw(. lib);
timothy@apple.comf42518d2008-02-06 20:19:16 +000030
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000031use Bugzilla;
32use Bugzilla::Error;
33use Bugzilla::Bug;
timothy@apple.comf42518d2008-02-06 20:19:16 +000034
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000035use List::Util qw(max);
36
37my $user = Bugzilla->login();
timothy@apple.comf42518d2008-02-06 20:19:16 +000038
39my $cgi = Bugzilla->cgi;
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000040my $template = Bugzilla->template;
41my $vars = {};
timothy@apple.comf42518d2008-02-06 20:19:16 +000042# Connect to the shadow database if this installation is using one to improve
43# performance.
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000044my $dbh = Bugzilla->switch_to_shadow_db();
timothy@apple.comf42518d2008-02-06 20:19:16 +000045
46################################################################################
47# Data/Security Validation #
48################################################################################
49
50# Make sure the bug ID is a positive integer representing an existing
51# bug that the user is authorized to access.
ddkilzer@apple.com097da082009-07-03 02:14:25 +000052my $id = $cgi->param('id') || ThrowUserError('improper_bug_id_field_value');
timothy@apple.comf42518d2008-02-06 20:19:16 +000053ValidateBugID($id);
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000054my $current_bug = new Bugzilla::Bug($id);
timothy@apple.comf42518d2008-02-06 20:19:16 +000055
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000056local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0;
timothy@apple.comf42518d2008-02-06 20:19:16 +000057
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000058local our $maxdepth = $cgi->param('maxdepth') || 0;
timothy@apple.comf42518d2008-02-06 20:19:16 +000059if ($maxdepth !~ /^\d+$/) { $maxdepth = 0 };
60
61################################################################################
62# Main Section #
63################################################################################
64
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000065# Stores the greatest depth to which either tree goes.
66local our $realdepth = 0;
timothy@apple.comf42518d2008-02-06 20:19:16 +000067
68# Generate the tree of bugs that this bug depends on and a list of IDs
69# appearing in the tree.
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000070my $dependson_tree = { $id => $current_bug };
timothy@apple.comf42518d2008-02-06 20:19:16 +000071my $dependson_ids = {};
72GenerateTree($id, "dependson", 1, $dependson_tree, $dependson_ids);
73$vars->{'dependson_tree'} = $dependson_tree;
74$vars->{'dependson_ids'} = [keys(%$dependson_ids)];
75
76# Generate the tree of bugs that this bug blocks and a list of IDs
77# appearing in the tree.
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +000078my $blocked_tree = { $id => $current_bug };
timothy@apple.comf42518d2008-02-06 20:19:16 +000079my $blocked_ids = {};
80GenerateTree($id, "blocked", 1, $blocked_tree, $blocked_ids);
81$vars->{'blocked_tree'} = $blocked_tree;
82$vars->{'blocked_ids'} = [keys(%$blocked_ids)];
83
84$vars->{'realdepth'} = $realdepth;
85
86$vars->{'bugid'} = $id;
87$vars->{'maxdepth'} = $maxdepth;
88$vars->{'hide_resolved'} = $hide_resolved;
timothy@apple.comf42518d2008-02-06 20:19:16 +000089
90print $cgi->header();
91$template->process("bug/dependency-tree.html.tmpl", $vars)
92 || ThrowTemplateError($template->error());
93
94################################################################################
95# Recursive Tree Generation Function #
96################################################################################
97
98sub GenerateTree {
99 # Generates a dependency tree for a given bug. Calls itself recursively
100 # to generate sub-trees for the bug's dependencies.
timothy@apple.comf42518d2008-02-06 20:19:16 +0000101 my ($bug_id, $relationship, $depth, $bugs, $ids) = @_;
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +0000102
103 my @dependencies;
104 if ($relationship eq 'dependson') {
105 @dependencies = @{$bugs->{$bug_id}->dependson};
106 }
107 else {
108 @dependencies = @{$bugs->{$bug_id}->blocked};
109 }
110
timothy@apple.comf42518d2008-02-06 20:19:16 +0000111 # Don't do anything if this bug doesn't have any dependencies.
112 return unless scalar(@dependencies);
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +0000113
timothy@apple.comf42518d2008-02-06 20:19:16 +0000114 # Record this depth in the global $realdepth variable if it's farther
115 # than we've gone before.
116 $realdepth = max($realdepth, $depth);
117
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}) {
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +0000123 $bugs->{$dep_id} = new Bugzilla::Bug($dep_id);
timothy@apple.comf42518d2008-02-06 20:19:16 +0000124 GenerateTree($dep_id, $relationship, $depth+1, $bugs, $ids);
125 }
126
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).
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +0000131 if (!$bugs->{$dep_id}->{'error'}
132 && Bugzilla->user->can_see_bug($dep_id)
timothy@apple.comf42518d2008-02-06 20:19:16 +0000133 && (!$maxdepth || $depth <= $maxdepth)
ddkilzer@apple.com097da082009-07-03 02:14:25 +0000134 && ($bugs->{$dep_id}->isopened || !$hide_resolved))
timothy@apple.comf42518d2008-02-06 20:19:16 +0000135 {
ddkilzer@apple.comf3615fc2009-07-03 02:13:41 +0000136 # 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);
timothy@apple.comf42518d2008-02-06 20:19:16 +0000139 $ids->{$dep_id} = 1;
140 }
141 }
142}