%# BEGIN BPS TAGGED BLOCK {{{ %# %# COPYRIGHT: %# %# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) %# %# %# LICENSE: %# %# This work is made available to you under the terms of Version 2 of %# the GNU General Public License. A copy of that license should have %# been provided with this software, but in any event can be snarfed %# from www.gnu.org. %# %# This work is distributed in the hope that it will be useful, but %# WITHOUT ANY WARRANTY; without even the implied warranty of %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %# General Public License for more details. %# %# You should have received a copy of the GNU General Public License %# along with this program; if not, write to the Free Software %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA %# 02110-1301 or visit their web page on the internet at %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. %# %# %# CONTRIBUTION SUBMISSION POLICY: %# %# (The following paragraph is not intended to limit the rights granted %# to you to modify and distribute this software under the terms of %# the GNU General Public License and is only of importance to you if %# you choose to contribute your changes and enhancements to the %# community by submitting them to Best Practical Solutions, LLC.) %# %# By intentionally submitting any modifications, corrections or %# derivatives to this work, or any other work intended for use with %# Request Tracker, to Best Practical Solutions, LLC, you confirm that %# you are the copyright holder for those contributions and you grant %# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, %# royalty-free, perpetual, license to use, copy, create derivative %# works based on those contributions, and sublicense and distribute %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} <& /Elements/Header, Title => loc('Browse by topic') &> <& /Elements/Tabs &> <& /Elements/ListActions, actions => \@Actions &> <&|/l&>All topics % if (defined $class) { > <% $currclass_name %> % } % if ($id != 0) { > <& /Articles/Elements/ShowTopic, topic => $currtopic &> % }

# <&|/l&>Browse by topic

<%perl> if (defined $class) { $m->print('

## '.''.$currclass_name."

\n"); ProduceTree(\@Actions, $currclass, $currclass_id, $currclass_name, 0, $id); } else { $m->print("

\n"); while (my $c = $Classes->Next) { $m->print('

- ## '.''.$c->Name."

  \n"); $m->print("\n
\n"); } $m->print(qq|

- ## |.loc('Global Topics').qq|

\n|); $m->print("

\n"); }
<%perl> my @articles; if ($id or $showall) { my $Articles = RT::ObjectTopics->new($session{'CurrentUser'}); $Articles->Limit(FIELD => 'ObjectType', VALUE => 'RT::Article'); if ($id) { $Articles->Limit(FIELD => 'Topic', VALUE => $id, ENTRYAGGREGATOR => 'OR'); if ($showall) { my $kids = $currtopic->Children; while (my $k = $kids->Next) { $Articles->Limit(FIELD => 'Topic', VALUE => $k->Id, ENTRYAGGREGATOR => 'OR'); } } } @articles = map {$a = RT::Article->new($session{'CurrentUser'}); $a->Load($_->ObjectId); $a} @{$Articles->ItemsArrayRef} } elsif ($class) { my $Articles = RT::Articles->new($session{'CurrentUser'}); my $TopicsAlias = $Articles->Join( TYPE => 'left', ALIAS1 => 'main', FIELD1 => 'id', TABLE2 => 'ObjectTopics', FIELD2 => 'ObjectId', ); $Articles->Limit( LEFTJOIN => $TopicsAlias, FIELD => 'ObjectType', VALUE => 'RT::Article', ); $Articles->Limit( ALIAS => $TopicsAlias, FIELD => 'Topic', OPERATOR => 'IS', VALUE => 'NULL', QUOTEVALUE => 0, ); $Articles->Limit( FIELD => 'Class', OPERATOR => '=', VALUE => $class, ); @articles = @{$Articles->ItemsArrayRef}; } % if (@articles) { % if ($id) {

## <&|/l, $currtopic->Name&>Articles in [_1]

% } elsif ($class) {

## <&|/l&>Articles with no topics

% }

% for my $a (@articles) {
- <% $a->Name || loc("(no name)") %>
% }

% } <%init> my @Actions; my $Classes; my $currclass; my $currclass_id; my $currclass_name; my $currtopic; if ( defined $class ) { if ($class) { $currclass = RT::Class->new( $session{'CurrentUser'} ); $currclass->Load($class); $currclass_id = $currclass->Id; $currclass_name = $currclass->Name; } else { $currclass = $RT::System; $currclass_id = 0; $currclass_name = 'Global Topics'; } } else { $Classes = RT::Classes->new( $session{'CurrentUser'} ); $Classes->LimitToEnabled(); } if ($id) { $currtopic = RT::Topic->new( $session{'CurrentUser'} ); $currtopic->Load($id); } # A subroutine that iterates through topics and their children, producing # the necessary ul, li, and href links for the table of contents. Thank # heaven for query caching. The $restrict variable is used to display only # the branch of the hierarchy which contains that topic ID. sub ProduceTree { my ( $Actions, $currclass, $currclass_id, $currclass_name, $parentid, $restrictid ) = @_; $parentid = 0 unless $parentid; # Deal with tree restriction, if any. if ($restrictid) { my $rtopic = RT::Topic->new( $session{'CurrentUser'} ); $rtopic->Load($restrictid); unless ( $rtopic->Id() && $rtopic->ObjectId() == $currclass_id ) { push( @{$Actions},"Could not restrict view to topic $restrictid"); # Start over, without the restriction. &ProduceTree( $Actions, $currclass, $currclass_id, $currclass_name, $parentid, undef ); } else { my @showtopics; push( @showtopics, $rtopic ); my $parent = $rtopic->ParentObj; while ( $parent->Id ) { push( @showtopics, $parent ); my $newparent = $parent->ParentObj; $parent = $newparent; } # List the topics. my $indents = @showtopics; while ( my $t = pop @showtopics ) { print "

"; print &MakeLinks( $t, $currclass, $currclass_id, $currclass_name, $t->Children->Count ); if ( $t->Id == $restrictid ) { &ProduceTree( $Actions, $currclass, $currclass_id, $currclass_name, $restrictid, undef ); } } print "

" x $indents; } } else { # No restriction in place. Build the entire tree. my $topics = RT::Topics->new( $session{'CurrentUser'} ); $topics->LimitToObject($currclass); $topics->LimitToKids($parentid); $topics->OrderBy( FIELD => 'Name' ); print "

" if $topics->Count; while ( my $t = $topics->Next ) { if ( $t->Children->Count ) { print &MakeLinks( $t, $currclass, $currclass_id, $currclass_name, 1 ); &ProduceTree( $Actions, $currclass, $currclass_id, $currclass_name, $t->Id ); } else { print &MakeLinks( $t, $currclass, $currclass_id, $currclass_name, 0 ); } } print "

\n" if $topics->Count; } } sub MakeLinks { my ( $topic, $currclass, $currclass_id, $currclass_name, $haschild ) = @_; my $query; my $output; if ( ref($topic) eq 'RT::Topic' ) { my $topic_info = $topic->Name() || loc("(no name)"); $topic_info .= ": " . $topic->Description() if $topic->Description; if ($haschild) { # has topics below it $query = "Topics.html?id=" . $topic->Id . "&class=" . $currclass_id; $output = qq(
- $topic_info); } else { $output = qq(
- $topic_info); } my $Articles = RT::ObjectTopics->new( $session{'CurrentUser'} ); $Articles->Limit( FIELD => 'ObjectType', VALUE => 'RT::Article' ); $Articles->Limit( FIELD => 'Topic', VALUE => $topic->Id ); if ( $Articles->Count ) { my $article_text = " (" . loc( "[quant,_1,article]", $Articles->Count ) . ")"; my $query = "Topics.html?id=" . $topic->Id . "&class=$currclass_id&showall=1"; $output .= qq($article_text); } $output .= "
\n"; } else { # This builds a link for the class specified, with no particular topic. $query = "Topics.html?class=" . $currclass_id; $output = "
- " . $currclass_name . ""; $output .= ": " . $currclass->Description if $currclass->Description; } return $output; } <%args> $id => 0 $class => undef $showall => undef