ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 1 | #!/usr/bin/perl -T |
| 2 | # This Source Code Form is subject to the terms of the Mozilla Public |
| 3 | # License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 5 | # |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 6 | # This Source Code Form is "Incompatible With Secondary Licenses", as |
| 7 | # defined by the Mozilla Public License, v. 2.0. |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 8 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 9 | use 5.10.1; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 10 | use strict; |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 11 | use warnings; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 12 | |
ddkilzer@apple.com | 097da08 | 2009-07-03 02:14:25 +0000 | [diff] [blame] | 13 | use lib qw(. lib); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 14 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 15 | use Bugzilla; |
| 16 | use Bugzilla::Error; |
| 17 | use Bugzilla::Bug; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 18 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 19 | use List::Util qw(max); |
| 20 | |
| 21 | my $user = Bugzilla->login(); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 22 | |
| 23 | my $cgi = Bugzilla->cgi; |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 24 | my $template = Bugzilla->template; |
| 25 | my $vars = {}; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 26 | # Connect to the shadow database if this installation is using one to improve |
| 27 | # performance. |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 28 | my $dbh = Bugzilla->switch_to_shadow_db(); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 29 | |
| 30 | ################################################################################ |
| 31 | # Data/Security Validation # |
| 32 | ################################################################################ |
| 33 | |
| 34 | # Make sure the bug ID is a positive integer representing an existing |
| 35 | # bug that the user is authorized to access. |
ddkilzer@apple.com | 5777284 | 2014-10-16 16:00:58 +0000 | [diff] [blame] | 36 | my $bug = Bugzilla::Bug->check(scalar $cgi->param('id')); |
| 37 | my $id = $bug->id; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 38 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 39 | local our $hide_resolved = $cgi->param('hide_resolved') ? 1 : 0; |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 40 | local our $maxdepth = $cgi->param('maxdepth') || 0; |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 41 | if ($maxdepth !~ /^\d+$/) { |
| 42 | $maxdepth = 0; |
| 43 | } |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 44 | |
| 45 | ################################################################################ |
| 46 | # Main Section # |
| 47 | ################################################################################ |
| 48 | |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 49 | # Stores the greatest depth to which either tree goes. |
| 50 | local our $realdepth = 0; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 51 | |
| 52 | # Generate the tree of bugs that this bug depends on and a list of IDs |
| 53 | # appearing in the tree. |
ddkilzer@apple.com | 5777284 | 2014-10-16 16:00:58 +0000 | [diff] [blame] | 54 | my $dependson_tree = { $id => $bug }; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 55 | my $dependson_ids = {}; |
| 56 | GenerateTree($id, "dependson", 1, $dependson_tree, $dependson_ids); |
| 57 | $vars->{'dependson_tree'} = $dependson_tree; |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 58 | $vars->{'dependson_ids'} = [keys(%$dependson_ids)]; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 59 | |
| 60 | # Generate the tree of bugs that this bug blocks and a list of IDs |
| 61 | # appearing in the tree. |
ddkilzer@apple.com | 5777284 | 2014-10-16 16:00:58 +0000 | [diff] [blame] | 62 | my $blocked_tree = { $id => $bug }; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 63 | my $blocked_ids = {}; |
| 64 | GenerateTree($id, "blocked", 1, $blocked_tree, $blocked_ids); |
| 65 | $vars->{'blocked_tree'} = $blocked_tree; |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 66 | $vars->{'blocked_ids'} = [keys(%$blocked_ids)]; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 67 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 68 | $vars->{'bugid'} = $id; |
| 69 | $vars->{'realdepth'} = $realdepth; |
| 70 | $vars->{'maxdepth'} = $maxdepth; |
| 71 | $vars->{'hide_resolved'} = $hide_resolved; |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 72 | |
| 73 | print $cgi->header(); |
| 74 | $template->process("bug/dependency-tree.html.tmpl", $vars) |
| 75 | || ThrowTemplateError($template->error()); |
| 76 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 77 | # Tree Generation Functions |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 78 | |
| 79 | sub GenerateTree { |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 80 | my ($bug_id, $relationship, $depth, $bugs, $ids) = @_; |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 81 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 82 | # determine just the list of bug ids |
| 83 | _generate_bug_ids($bug_id, $relationship, $depth, $ids); |
| 84 | my $bug_ids = [ keys %$ids ]; |
| 85 | return unless @$bug_ids; |
| 86 | |
| 87 | # load all the bugs at once |
| 88 | foreach my $bug (@{ Bugzilla::Bug->new_from_list($bug_ids) }) { |
| 89 | if (!$bug->{error}) { |
| 90 | $bugs->{$bug->id} = $bug; |
| 91 | } |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 92 | } |
| 93 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 94 | # preload bug visibility |
| 95 | Bugzilla->user->visible_bugs($bug_ids); |
ddkilzer@apple.com | f3615fc | 2009-07-03 02:13:41 +0000 | [diff] [blame] | 96 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 97 | # and generate the tree |
| 98 | _generate_tree($bug_id, $relationship, $depth, $bugs, $ids); |
| 99 | } |
| 100 | |
| 101 | sub _generate_bug_ids { |
| 102 | my ($bug_id, $relationship, $depth, $ids) = @_; |
| 103 | |
| 104 | # Record this depth in the global $realdepth variable if it's farther |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 105 | # than we've gone before. |
| 106 | $realdepth = max($realdepth, $depth); |
| 107 | |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 108 | my $dependencies = _get_dependencies($bug_id, $relationship); |
| 109 | foreach my $dep_id (@$dependencies) { |
| 110 | if (!$maxdepth || $depth <= $maxdepth) { |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 111 | $ids->{$dep_id} = 1; |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 112 | _generate_bug_ids($dep_id, $relationship, $depth + 1, $ids); |
timothy@apple.com | f42518d | 2008-02-06 20:19:16 +0000 | [diff] [blame] | 113 | } |
| 114 | } |
| 115 | } |
ddkilzer@apple.com | 8040bb0 | 2017-03-21 16:27:49 +0000 | [diff] [blame] | 116 | |
| 117 | sub _generate_tree { |
| 118 | my ($bug_id, $relationship, $depth, $bugs, $ids) = @_; |
| 119 | |
| 120 | my $dependencies = _get_dependencies($bug_id, $relationship); |
| 121 | |
| 122 | foreach my $dep_id (@$dependencies) { |
| 123 | # recurse |
| 124 | if (!$maxdepth || $depth < $maxdepth) { |
| 125 | _generate_tree($dep_id, $relationship, $depth + 1, $bugs, $ids); |
| 126 | } |
| 127 | |
| 128 | # remove bugs according to visiblity |
| 129 | if (!Bugzilla->user->can_see_bug($dep_id)) { |
| 130 | delete $ids->{$dep_id}; |
| 131 | } |
| 132 | elsif (!grep { $_ == $dep_id } @{ $bugs->{dependencies}->{$bug_id} }) { |
| 133 | push @{ $bugs->{dependencies}->{$bug_id} }, $dep_id; |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | sub _get_dependencies { |
| 139 | my ($bug_id, $relationship) = @_; |
| 140 | my $cache = Bugzilla->request_cache->{dependency_cache} ||= {}; |
| 141 | return $cache->{$bug_id}->{$relationship} ||= |
| 142 | $relationship eq 'dependson' |
| 143 | ? Bugzilla::Bug::EmitDependList('blocked', 'dependson', $bug_id, $hide_resolved) |
| 144 | : Bugzilla::Bug::EmitDependList('dependson', 'blocked', $bug_id, $hide_resolved); |
| 145 | } |
| 146 | |