ddkilzer@apple.com | f573e63 | 2009-07-03 02:14:39 +0000 | [diff] [blame] | 1 | #!/usr/bin/env perl -wT |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 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> |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 25 | # Frédéric Buclin <LpSolit@gmail.com> |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 26 | |
| 27 | use strict; |
| 28 | |
ddkilzer@apple.com | 097da08 | 2009-07-03 02:14:25 +0000 | [diff] [blame] | 29 | use lib qw(. lib); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 30 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 31 | use Bugzilla; |
| 32 | use Bugzilla::Error; |
| 33 | use Bugzilla::Bug; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 34 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 35 | use List::Util qw(max); |
| 36 | |
| 37 | my $user = Bugzilla->login(); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 38 | |
| 39 | my $cgi = Bugzilla->cgi; |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 40 | my $template = Bugzilla->template; |
| 41 | my $vars = {}; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 42 | # Connect to the shadow database if this installation is using one to improve |
| 43 | # performance. |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 44 | my $dbh = Bugzilla->switch_to_shadow_db(); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 45 | |
| 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.com | 097da08 | 2009-07-03 02:14:25 +0000 | [diff] [blame] | 52 | my $id = $cgi->param('id') || ThrowUserError('improper_bug_id_field_value'); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 53 | ValidateBugID($id); |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 54 | my $current_bug = new Bugzilla::Bug($id); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 55 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 56 | local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 57 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 58 | local our $maxdepth = $cgi->param('maxdepth') || 0; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 59 | if ($maxdepth !~ /^\d+$/) { $maxdepth = 0 }; |
| 60 | |
| 61 | ################################################################################ |
| 62 | # Main Section # |
| 63 | ################################################################################ |
| 64 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 65 | # Stores the greatest depth to which either tree goes. |
| 66 | local our $realdepth = 0; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 67 | |
| 68 | # Generate the tree of bugs that this bug depends on and a list of IDs |
| 69 | # appearing in the tree. |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 70 | my $dependson_tree = { $id => $current_bug }; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 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)]; |
| 75 | |
| 76 | # Generate the tree of bugs that this bug blocks and a list of IDs |
| 77 | # appearing in the tree. |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 78 | my $blocked_tree = { $id => $current_bug }; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 79 | my $blocked_ids = {}; |
| 80 | GenerateTree($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.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 89 | |
| 90 | print $cgi->header(); |
| 91 | $template->process("bug/dependency-tree.html.tmpl", $vars) |
| 92 | || ThrowTemplateError($template->error()); |
| 93 | |
| 94 | ################################################################################ |
| 95 | # Recursive Tree Generation Function # |
| 96 | ################################################################################ |
| 97 | |
| 98 | sub 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.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 101 | my ($bug_id, $relationship, $depth, $bugs, $ids) = @_; |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 102 | |
| 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.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 111 | # Don't do anything if this bug doesn't have any dependencies. |
| 112 | return unless scalar(@dependencies); |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 113 | |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 114 | # 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.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 123 | $bugs->{$dep_id} = new Bugzilla::Bug($dep_id); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 124 | 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.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 131 | if (!$bugs->{$dep_id}->{'error'} |
| 132 | && Bugzilla->user->can_see_bug($dep_id) |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 133 | && (!$maxdepth || $depth <= $maxdepth) |
ddkilzer@apple.com | 097da08 | 2009-07-03 02:14:25 +0000 | [diff] [blame] | 134 | && ($bugs->{$dep_id}->isopened || !$hide_resolved)) |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 135 | { |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 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); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 139 | $ids->{$dep_id} = 1; |
| 140 | } |
| 141 | } |
| 142 | } |