%ARGS>
$TreeviewMagic => undef
$id => undef
$Query => undef
$Format => undef
$Rows => undef
$OrderBy => undef
$Order => undef
$Page => undef
$MaxDepth => 7
$ShowChildren => undef
$ShowDependencies => undef
@ShowStatus => ();
%ARGS>
<%init>
my @statuses = RT::Queue->new($session{'CurrentUser'})->StatusArray;
unless ($TreeviewMagic) {
unless (defined $ShowChildren) {
$ShowChildren = 1;
}
unless (defined $ShowDependencies) {
$ShowDependencies = 1;
}
unless( @ShowStatus ) {
@ShowStatus = qw(new open stalled);
}
}
# {{{ Generic setup
my $title = loc('Tree view');
my $QueryString = "?".
$m->comp(
'/Elements/QueryString',
Query => $Query,
Format => $Format,
Rows => $Rows,
OrderBy => $OrderBy,
Order => $Order,
Page => $Page,
MaxDepth => $MaxDepth,
ShowChildren => $ShowChildren,
ShowDependencies => $ShowDependencies,
);
# QueryString couldn't handle array refs
$QueryString = join( '&', $QueryString,
map { 'ShowStatus='. $m->interp->apply_escapes($_,'u') }
@ShowStatus);
# }}}
# {{{ If we load a ticket, this search is on a given ticket and we'll get the
# ticket menus instead of the tree ones
my $Ticket;
if ($id) {
$Ticket = RT::Ticket->new( $session{'CurrentUser'} );
$Ticket->Load($id);
$Query = "id = $id";
}
# }}}
# {{{ Scrub the html of the format string to remove any potential nasties.
$Format = $m->comp( '/Elements/ScrubHTML', Content => ($Format||
$RT::DefaultSearchResultFormat));
my (@Format) =
$m->comp( '/Elements/CollectionAsTable/ParseFormat', Format => $Format );
# Alter the format to do treeview indents.
foreach my $entry (@Format) {
my @output;
foreach my $item ( @{ $entry->{'output'} } ) {
if ( $item eq '__Subject__' ) {
# add indent whitespaces before link
unshift @output, '___RT_TreeView_Indent__';
push @output, $item;
}
else {
push @output, $item;
}
}
if( lc $entry->{'attribute'} eq 'id' ) {
for my $item ( @output ) {
$item =~ s/{'output'} = \@output;
}
# }}}
my $tickets = RT::Tickets->new( $session{'CurrentUser'} );
$tickets->FromSQL($Query);
$tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order );
my @tickets = @{ $tickets->ItemsArrayRef || [] };
my $TopTickets = {};
$TopTickets->{ $_->id } = $_ foreach( @tickets );
my @tree;
foreach my $ticket (@tickets) {
# If the parent ticket hasn't been invalidated by being displayed deeper...
# recurse now and add it in
next unless exists $TopTickets->{ $ticket->id };
my $kids = build_subtree(
Ticket => $ticket,
TopTickets => $TopTickets,
Depth => 1,
MaxDepth => $MaxDepth,
ShowChildren => $ShowChildren,
ShowDependencies => $ShowDependencies,
ShowStatus => \@ShowStatus,
);
unless( $kids && @$kids ) {
next unless grep $_ eq $ticket->Status, @ShowStatus;
}
push @tree, [ $ticket, $kids ];
}
# Ok. Let's build up our tree of tickets, recursing down.
sub build_subtree {
my %args = (
Ticket => undef,
TopTickets => undef,
ShowChildren => undef,
ShowDependencies => undef,
ShowStatus => undef,
Depth => undef,
MaxDepth => undef,
@_
);
return if ( $args{'Depth'} > $args{'MaxDepth'} );
my @query;
push @query, 'DependsOn = ' . $args{'Ticket'}->id
if ( $args{'ShowDependencies'} );
push @query, 'MemberOf = ' . $args{'Ticket'}->id
if ( $args{'ShowChildren'} );
my $deps = RT::Tickets->new( $session{'CurrentUser'} );
$deps->FromSQL( join( ' OR ', @query ) );
$deps->OrderBy( FIELD => $args{'OrderBy'}, ORDER => $args{'Order'} );
my @tickets;
while ( my $dep = $deps->Next ) {
delete $args{'TopTickets'}->{ $dep->id };
my $kids = undef;
$kids = build_subtree(
%args,
Ticket => $dep,
Depth => $args{'Depth'} + 1,
);
unless( $kids && @$kids ) {
next unless grep $_ eq $dep->Status, @{ $args{'ShowStatus'} };
}
push @tickets, [ $dep, $kids ];
}
return ( \@tickets );
}
%init>
<& /Elements/Header, Title => $title, Refresh => $session{'tickets_refresh_interval'} &>
<& /Ticket/Elements/Tabs,
current_tab => "Search/Tree.html".$QueryString,
Ticket => $Ticket,
Title => $title,
Format => $Format,
Query => $Query,
Rows => $Rows,
OrderBy => $OrderBy,
Order => $Order &>