%ARGS> $TreeviewMagic => undef $id => undef $Query => undef $Format => undef $Rows => undef $OrderBy => undef $Order => undef $Page => undef $MaxDepth => 7 $ShowChildren => undef $ShowDependencies => undef %ARGS> <%init> unless ($TreeviewMagic) { unless (defined $ShowChildren) { $ShowChildren = 1; } unless (defined $ShowDependencies) { $ShowDependencies = 1; } } # {{{ 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 ); # }}} # {{{ 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.a $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__' ) { push @output, '___RT_TreeView_Indent__', $item; } else { push @output, $item; } } $entry->{'output'} = \@output; } # }}} my $tickets = RT::Tickets->new( $session{'CurrentUser'} ); $tickets->FromSQL($Query); $tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order ); my $TopTickets = (); my @tickets = @{ $tickets->ItemsArrayRef || [] }; foreach my $ticket (@tickets) { $TopTickets->{ $ticket->id } = $ticket; } 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 ); 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, Depth => undef, MaxDepth => undef, @_ ); return if ( $args{'Depth'} > $args{'MaxDepth'} ); my $ticket = $args{'Ticket'}; my $TopTickets = $args{'TopTickets'}; my $deps = RT::Tickets->new( $session{'CurrentUser'} ); my @query; my @tickets; push @query, 'DependentOn = ' . $ticket->id if ( $args{'ShowDependencies'} ); push @query, 'MemberOf = ' . $ticket->id if ( $args{'ShowChildren'} ); $deps->FromSQL( join( ' OR ', @query ) ); $deps->OrderBy( FIELD => $args{'OrderBy'}, ORDER => $args{'Order'} ); while ( my $dep = $deps->Next ) { delete $TopTickets->{ $dep->id }; my $kids = undef; $kids = build_subtree( Ticket => $dep, TopTickets => $TopTickets, Depth => ( $args{'Depth'} + 1 ), MaxDepth => $args{'MaxDepth'}, ShowChildren => $args{'ShowChildren'}, ShowDependencies => $args{'ShowDependencies'} ); 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 &>