summaryrefslogtreecommitdiff
path: root/rt/share/html/Articles
diff options
context:
space:
mode:
Diffstat (limited to 'rt/share/html/Articles')
-rw-r--r--rt/share/html/Articles/Article/Delete.html106
-rw-r--r--rt/share/html/Articles/Article/Display.html92
-rw-r--r--rt/share/html/Articles/Article/Edit.html333
-rw-r--r--rt/share/html/Articles/Article/Elements/EditBasics73
-rw-r--r--rt/share/html/Articles/Article/Elements/EditCustomFields83
-rw-r--r--rt/share/html/Articles/Article/Elements/EditLinks113
-rw-r--r--rt/share/html/Articles/Article/Elements/EditTopics147
-rw-r--r--rt/share/html/Articles/Article/Elements/LinkEntryInstructions49
-rw-r--r--rt/share/html/Articles/Article/Elements/Preformatted127
-rw-r--r--rt/share/html/Articles/Article/Elements/SearchByCustomField70
-rw-r--r--rt/share/html/Articles/Article/Elements/SelectSavedSearches76
-rw-r--r--rt/share/html/Articles/Article/Elements/SelectSearchPrivacy62
-rw-r--r--rt/share/html/Articles/Article/Elements/ShowHistory76
-rw-r--r--rt/share/html/Articles/Article/Elements/ShowLinks92
-rw-r--r--rt/share/html/Articles/Article/Elements/ShowSavedSearches85
-rw-r--r--rt/share/html/Articles/Article/Elements/ShowSearchCriteria171
-rw-r--r--rt/share/html/Articles/Article/Elements/ShowTopics58
-rw-r--r--rt/share/html/Articles/Article/ExtractFromTicket.html105
-rw-r--r--rt/share/html/Articles/Article/ExtractIntoClass.html76
-rw-r--r--rt/share/html/Articles/Article/ExtractIntoTopic.html72
-rw-r--r--rt/share/html/Articles/Article/History.html57
-rw-r--r--rt/share/html/Articles/Article/PreCreate.html62
-rw-r--r--rt/share/html/Articles/Article/Search.html269
-rw-r--r--rt/share/html/Articles/Elements/BeforeMessageBox239
-rw-r--r--rt/share/html/Articles/Elements/CheckSkipCreate76
-rw-r--r--rt/share/html/Articles/Elements/CreateArticle59
-rw-r--r--rt/share/html/Articles/Elements/GotoArticle73
-rw-r--r--rt/share/html/Articles/Elements/IncludeArticle99
-rw-r--r--rt/share/html/Articles/Elements/NewestArticles80
-rw-r--r--rt/share/html/Articles/Elements/QuickSearch59
-rw-r--r--rt/share/html/Articles/Elements/SelectClass95
-rw-r--r--rt/share/html/Articles/Elements/ShowTopic64
-rw-r--r--rt/share/html/Articles/Elements/UpdatedArticles81
-rw-r--r--rt/share/html/Articles/Topics.html276
-rw-r--r--rt/share/html/Articles/index.html63
35 files changed, 3718 insertions, 0 deletions
diff --git a/rt/share/html/Articles/Article/Delete.html b/rt/share/html/Articles/Article/Delete.html
new file mode 100644
index 000000000..7abd824d5
--- /dev/null
+++ b/rt/share/html/Articles/Article/Delete.html
@@ -0,0 +1,106 @@
+%# 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 => $title &>
+<& /Elements/Tabs &>
+
+% if ($ARGS{'Delete'}) {
+<%$title%>
+<& /Elements/ListActions, actions => \@results &>
+
+% } else {
+<b><&|/l&>Are you sure you want to delete this article?</&></b>
+<table>
+<tr>
+<td align="left">
+<form action="Display.html" method="get">
+<input type="hidden" name="id" value="<%$ArticleObj->Id%>" />
+<input type="submit" value="<&|/l&>No</&>" />
+</form>
+
+</td>
+<td align="right">
+<form action="Delete.html" method="post">
+<input type="hidden" name="id" value="<%$ArticleObj->Id%>" />
+<input type="hidden" name="Delete" value="yes" />
+<input type="submit" value="<&|/l&>Yes</&>" />
+</form>
+</td>
+
+</tr>
+</table>
+% }
+<%INIT>
+
+my @results;
+
+my $title;
+my $ArticleObj = RT::Article->new( $session{'CurrentUser'} );
+
+
+$ArticleObj->Load($id);
+unless ( $ArticleObj->id ) {
+ $m->comp("/Elements/Error", Why => loc("Unable to load article") );
+}
+
+
+unless ( $ArticleObj->CurrentUserHasRight('ModifyArticle') ) {
+ $m->comp("/Elements/Error", Why => loc("No permission to modify article"));
+}
+
+if ($ARGS{'Delete'} eq 'yes') {
+ $ArticleObj->Delete();
+ $title = loc('Article #[_1] deleted', $ArticleObj->Id);
+}
+
+else {
+ $title = loc('Delete article #[_1]', $ArticleObj->Id);
+}
+</%INIT>
+<%ARGS>
+$id => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Display.html b/rt/share/html/Articles/Article/Display.html
new file mode 100644
index 000000000..b80dc1c5e
--- /dev/null
+++ b/rt/share/html/Articles/Article/Display.html
@@ -0,0 +1,92 @@
+%# 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 => $title &>
+<& /Elements/Tabs &>
+<h2><&|/l&>Basics</&></h2>
+<span class="label"><&|/l&>Class</&></span>: <span class="value"><%$article->ClassObj->Name%></span><br />
+<em><span class="value"><%$article->Summary%></span></em>
+<h2><&|/l&>Content</&></h2>
+<& /Elements/ShowCustomFields, Object => $article &>
+
+<h2><&|/l&>Links</&></h2>
+<& Elements/ShowLinks, article => $article &>
+
+<h2><&|/l&>Topics</&></h2>
+<& Elements/ShowTopics, article => $article &>
+<%init>
+
+my $article = RT::Article->new( $session{'CurrentUser'} );
+if ($Name) {
+ $article->LoadByCols( Name => $Name );
+}
+elsif ($id) {
+ $article->Load($id);
+}
+unless ( $article->Id ) {
+ if ( $ARGS{'Name'} ) {
+ $m->comp( 'Edit.html', %ARGS );
+ return ();
+ }
+ else {
+ $m->comp( "/Elements/Error", Why => loc("Article not found") );
+ }
+
+}
+
+unless ( $article->CurrentUserHasRight('ShowArticle') ) {
+ $m->comp( "/Elements/Error", Why => loc("Permission Denied") );
+}
+my $title = loc( "Article #[_1]: [_2]", $article->Id, $article->Name || loc("(no name)"));
+
+$id = $article->id;
+
+</%init>
+<%args>
+$id => undef
+$Name => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/Edit.html b/rt/share/html/Articles/Article/Edit.html
new file mode 100644
index 000000000..756aa2cc9
--- /dev/null
+++ b/rt/share/html/Articles/Article/Edit.html
@@ -0,0 +1,333 @@
+%# 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 => $title &>
+<& /Elements/Tabs &>
+<& /Elements/ListActions, actions => \@results &>
+
+<form method="post" action="Edit.html" name="EditArticle" id="EditArticle" enctype="multipart/form-data">
+<input type="hidden" name="next" value="<%$ARGS{next}||''%>" />
+<input type="hidden" name="id" value="<%$id%>" />
+<table width="100%">
+<tr>
+<td><h2><&|/l&>Basics</&></h2></td>
+<td></td>
+</tr>
+<& Elements/EditBasics, ArticleObj => $ArticleObj,
+ EditClass =>$EditClass,
+ ClassObj => $ClassObj,
+ %ARGS ,
+ id => $id
+ &>
+
+<tr>
+<td><h2><&|/l&>Content</&></h2></td>
+<td></td>
+</tr>
+<& Elements/EditCustomFields, ArticleObj => $ArticleObj,
+ CFContent => \%CFContent,
+ ClassObj => $ClassObj,
+ %ARGS,
+ id =>$id,
+ &>
+
+<tr>
+<td><h2><&|/l&>Links</&></h2></td>
+<td></td>
+</tr>
+<& Elements/EditLinks, ArticleObj => $ArticleObj,
+ %ARGS,
+ id => $id
+ &>
+<tr>
+<td><h2><&|/l&>Topics</&></h2></td>
+<td></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Topics</&></td>
+<td>
+<& Elements/EditTopics, ArticleObj => $ArticleObj,
+ Classes => [$ArticleObj->Id ? $ArticleObj->ClassObj : $ClassObj],
+ OnlyThisClass => 1,
+ %ARGS,
+ id => $id
+ &>
+</td>
+</tr>
+</table>
+<& /Elements/Submit, Label => ($id eq 'new' ? loc('Create') : loc('Save Changes')), color => "#993333" &>
+</form>
+
+<%INIT>
+
+if ( exists $ARGS{'Topics'} ) {
+ $ARGS{'Topics'} =
+ ref( $ARGS{'Topics'} ) ? $ARGS{'Topics'} : [ $ARGS{'Topics'} ];
+}
+
+my @results;
+my $title;
+
+my $Entries = {};
+my $ArticleObj = RT::Article->new( $session{'CurrentUser'} );
+my $ClassObj = RT::Class->new( $session{'CurrentUser'} );
+my %create_args;
+my %CFContent;
+my $EditClass = 1;
+if ( !$id ) {
+ $title = loc('Create a new article');
+ foreach my $arg ( sort keys %ARGS ) {
+ if ( $arg =~ /^Transaction-(\d+)$/ ) {
+ my $trans = RT::Transaction->new( $session{'CurrentUser'} );
+ $trans->Load($1);
+ $CFContent{ $ARGS{$arg} } .= "\n\n" if $CFContent{ $ARGS{$arg} };
+ $CFContent{ $ARGS{$arg} } .= $trans->Content;
+ }
+ }
+
+ $ClassObj->Load($Class);
+ unless ( $ClassObj->Id ) {
+ $m->comp( "/Elements/Error",
+ Why => loc( "'[_1]' isn't a valid class identifier", $Class ) );
+ }
+ $EditClass = 0;
+ $id = 'new';
+}
+elsif ( $id eq 'new' ) {
+
+ if ( $ARGS{'RefersTo-new'} ) {
+ @{ $create_args{'RefersTo-new'} } =
+ split( /\s+/, $ARGS{'RefersTo-new'} );
+ }
+
+ if ( $ARGS{'new-RefersTo'} ) {
+ @{ $create_args{'new-RefersTo'} } =
+ split( /\s+/, $ARGS{'new-RefersTo'} );
+ }
+
+
+ foreach my $arg (keys %ARGS) {
+ next if $arg =~ /-(?:Magic|Category)$/;
+ # Object-RT::Article--CustomField-3-Values
+ if ( $arg =~ /^Object-RT::Article--CustomField-(\d+)(.*?)$/ ) {
+ my $cfid = $1;
+
+ my $cf = RT::CustomField->new( $session{'CurrentUser'} );
+ $cf->Load( $cfid );
+ unless ( $cf->id ) {
+ $RT::Logger->error( "Couldn't load custom field #". $cfid );
+ next;
+ }
+
+ if ( $arg =~ /-Upload$/ ) {
+ $create_args{"CustomField-$cfid"} = _UploadedFile( $arg );
+ next;
+ }
+
+ my $type = $cf->Type;
+
+ my @values = ();
+ if ( ref $ARGS{ $arg } eq 'ARRAY' ) {
+ @values = @{ $ARGS{ $arg } };
+ } elsif ( $type =~ /text/i ) {
+ @values = ($ARGS{ $arg });
+ } else {
+ @values = split /\r*\n/, $ARGS{ $arg } || '';
+ }
+ @values = grep $_ ne '',
+ map {
+ s/\r+\n/\n/g;
+ s/^\s+//;
+ s/\s+$//;
+ $_;
+ }
+ grep defined, @values;
+
+ $create_args{"CustomField-$cfid"} = \@values;
+ }
+ }
+
+ my $msg;
+ ( $id, $msg ) = $ArticleObj->Create(
+ Summary => $ARGS{'Summary'},
+ Name => $ARGS{'Name'},
+ Class => $ARGS{'Class'},
+ Topics => $ARGS{'Topics'},
+ %create_args
+ );
+ push( @results, $msg );
+ if ($id) {
+
+
+ $ArticleObj->Load($id);
+
+ $title = loc( 'Modify article #[_1]', $ArticleObj->Id );
+ delete $ARGS{id};
+
+ if ( $ARGS{next} ) {
+ $m->redirect($ARGS{next});
+ }
+ else {
+ MaybeRedirectForResults(
+ Actions => \@results,
+ Arguments => { id => $ArticleObj->id },
+ );
+ }
+ }
+ if (!$id) {
+ $ClassObj->Load($Class);
+ unless ( $ClassObj->Id ) {
+ $m->comp( "/Elements/Error",
+ Why => loc( "'[_1]' isn't a valid class identifier", $Class ) );
+ }
+ $ArticleObj = RT::Article->new( $session{'CurrentUser'} );
+ $id = 'new';
+ $EditClass = 0;
+ $title = loc('Create a new article');
+ }
+}
+else {
+
+ $ArticleObj->Load($id);
+ unless ( $ArticleObj->id ) {
+ $m->comp( "/Elements/Error",
+ Why => loc("Unable to load article") );
+ }
+
+ my @attribs = qw(Name Summary Class);
+
+ @results = UpdateRecordObject(
+ AttributesRef => \@attribs,
+ Object => $ArticleObj,
+ ARGSRef => \%ARGS
+ );
+
+ my @cf_results = ProcessObjectCustomFieldUpdates(
+ Object => $ArticleObj,
+ ARGSRef => \%ARGS
+ );
+ @results = ( @results, @cf_results );
+
+ # Delete links that are gone gone gone.
+ foreach my $arg ( keys %ARGS ) {
+ if ( $arg =~ /DeleteLink-(.*?)-(RefersTo|MemberOf|RefersTo)-(.*)$/ ) {
+ my $base = $1;
+ my $type = $2;
+ my $target = $3;
+
+ my ( $val, $msg ) = $ArticleObj->DeleteLink(
+ Base => $base,
+ Type => $type,
+ Target => $target
+ );
+
+ push @results, $msg;
+
+ }
+
+ }
+
+ my @linktypes = qw(DependsOn MemberOf RefersTo );
+
+ foreach my $linktype (@linktypes) {
+
+ for my $luri ( split( / /, ( $ARGS{ $ArticleObj->Id . "-$linktype" } || '' )) ) {
+ $luri =~ s/\s*$//; # Strip trailing whitespace
+ my ( $val, $msg ) =
+ $ArticleObj->AddLink( Target => $luri, Type => $linktype );
+ push @results, $msg;
+ delete $ARGS{ $ArticleObj->Id . "-$linktype" } if $val;
+ }
+
+ for my $luri ( split( / /, ( $ARGS{ "$linktype-" . $ArticleObj->Id } || '' )) ) {
+ my ( $val, $msg ) =
+ $ArticleObj->AddLink( Base => $luri, Type => $linktype );
+ push @results, $msg;
+ delete $ARGS{ "$linktype-" . $ArticleObj->Id } if $val;
+ }
+
+ }
+
+ my %topics;
+ if ( $ARGS{'EditTopics'} ) {
+ $topics{$_}++ for @{ $ARGS{'Topics'} };
+ my $objTopics =
+ RT::ObjectTopics->new( $session{'CurrentUser'} );
+ $objTopics->LimitToObject($ArticleObj);
+ while ( my $t = $objTopics->Next ) {
+ $topics{ $t->Topic }--;
+ }
+ for my $id ( keys %topics ) {
+ if ( $topics{$id} > 0 ) {
+ my ( $val, $msg ) = $ArticleObj->AddTopic( Topic => $id );
+ push @results, $msg;
+ }
+ elsif ( $topics{$id} < 0 ) {
+ my ( $val, $msg ) = $ArticleObj->DeleteTopic( Topic => $id );
+ push @results, $msg;
+ }
+ }
+ }
+
+ $title = loc( 'Modify article #[_1]', $ArticleObj->Id );
+}
+
+# if they're working on an existing article
+if ( $ArticleObj->id ) {
+ unless ( $ArticleObj->CurrentUserHasRight('ShowArticle') ) {
+ $m->comp( "/Elements/Error",
+ Why => loc("No permission to view Article") );
+ }
+}
+
+</%INIT>
+
+
+<%ARGS>
+$id => undef
+$Class => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/EditBasics b/rt/share/html/Articles/Article/Elements/EditBasics
new file mode 100644
index 000000000..256d81610
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/EditBasics
@@ -0,0 +1,73 @@
+%# 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 }}}
+<tr>
+<td class="label"><&|/l&>Name</&></td>
+<td><input name="Name" value="<%($ARGS{'id'} eq 'new' ? '' : $ArticleObj->Name) || $ARGS{'Name'} || ''|h%>" size="50" /></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Summary</&></td>
+<td><input name="Summary" value="<%($ARGS{'id'} eq 'new' ? '' : $ArticleObj->Summary) || $ARGS{'Summary'} ||'' |h%>" size="50" /></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Class</&></td>
+<td>
+% if ($EditClass) {
+<& /Articles/Elements/SelectClass, Name => 'Class', Default =>$ArticleObj->ClassObj->Id&>
+% } else {
+<%$ClassObj->Name%>
+<input type="hidden" name="Class" value="<%$ClassObj->Id%>" />
+% }
+</td>
+</tr>
+<%INIT>
+</%INIT>
+<%ARGS>
+$EditClass => 1
+$ClassObj => undef
+$ArticleObj => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/EditCustomFields b/rt/share/html/Articles/Article/Elements/EditCustomFields
new file mode 100644
index 000000000..db719eb2e
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/EditCustomFields
@@ -0,0 +1,83 @@
+%# 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 }}}
+% while (my $CustomField = $CustomFields->Next()) {
+<tr>
+ <td class="labeltop"><b><%$CustomField->Name%></b><br /><i><%$CustomField->FriendlyType%></i></td>
+ <td class="entry"><& /Elements/EditCustomField,
+ Object => $ArticleObj,
+ CustomField => $CustomField,
+ NamePrefix => $NamePrefix,
+ Default =>
+ ($CFContent->{$CustomField->Id} ||
+ $ARGS{$NamePrefix .$CustomField->id .'-Values'} ||
+ $ARGS{$NamePrefix .$CustomField->id .'-Value'})
+ ,
+ Rows => 15,
+ Cols => 70
+ &></td>
+</tr>
+% }
+<%INIT>
+my $CustomFields;
+my $NamePrefix;
+
+if ($ArticleObj->id && $ArticleObj->ClassObj->id) {
+ $CustomFields = $ArticleObj->CustomFields();
+ $NamePrefix = "Object-RT::Article-".$ArticleObj->Id."-CustomField-";
+}
+else {
+ $CustomFields = $ClassObj->ArticleCustomFields();
+ $NamePrefix = "Object-RT::Article--CustomField-";
+}
+</%INIT>
+<%ARGS>
+$ArticleObj => undef
+$ClassObj => undef
+$CFContent => undef
+$id => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/EditLinks b/rt/share/html/Articles/Article/Elements/EditLinks
new file mode 100644
index 000000000..03b99c8d3
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/EditLinks
@@ -0,0 +1,113 @@
+%# 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 }}}
+<tr>
+<td class="label"></td>
+<td class="value"><i><&|/l&>Enter articles, tickets, or other URLs related to this article.</&>
+<& LinkEntryInstructions &></i>
+% unless ($id eq 'new') {
+<i><&|/l&>(Check boxes to delete)</&></i><br />
+% }
+</td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Refers to</&>:</td>
+<td><input name="<%$id%>-RefersTo" value="<%$ARGS{$id.'-RefersTo'}||''%>" /><br />
+<ul>
+% if ($id ne 'new') {
+% my $refersto = $ArticleObj->RefersTo;
+% while (my $link = $refersto->Next) {
+% my $member = $link->TargetURI;
+<li>
+<input type="CHECKBOX" name="DeleteLink--<%$link->Type%>-<%$link->Target%>" />
+% if ($link->TargetURI->IsLocal) {
+<a href="<%$member->Resolver->HREF%>"><% loc($member->Object->ObjectTypeStr) %> <%$member->Object->Id%></a>:
+% if (UNIVERSAL::isa($member->Object, "RT::Article") or UNIVERSAL::can($member->Object, 'Name')) {
+<%$member->Object->Name%>
+% } elsif (UNIVERSAL::isa($member->Object, "RT::Ticket") or UNIVERSAL::can($member->Object, 'Subject')) {
+<%$member->Object->Subject%>
+% }
+</a>
+% } else {
+<a href="<%$member->Resolver->HREF%>"><%$link->Target%></a>
+% }
+% }
+% }
+</ul>
+</td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Referred to by</&>:</td>
+<td><input name="RefersTo-<%$id%>" value="<%$ARGS{'RefersTo-'.$id}||''%>" />
+<br />
+<ul>
+% if ($id ne 'new') {
+% my $referredtoby = $ArticleObj->ReferredToBy;
+% while (my $link = $referredtoby->Next) {
+% my $member = $link->BaseURI;
+<li>
+<input type="CHECKBOX" name="DeleteLink-<%$link->Base%>-<%$link->Type%>-" />
+% if ($link->BaseURI->IsLocal) {
+<a href="<%$member->Resolver->HREF%>"><% loc($member->Object->ObjectTypeStr) %> <%$member->Object->Id%>:
+% if (UNIVERSAL::isa($member->Object, "RT::Article") or UNIVERSAL::can($member->Object, 'Name')) {
+<%$member->Object->Name%>
+% } elsif (UNIVERSAL::isa($member->Object, "RT::Ticket") or UNIVERSAL::can($member->Object, 'Subject')) {
+<%$member->Object->Subject%>
+% }
+</a>
+% } else {
+<a href="<%$member->Resolver->HREF%>"><%$link->Base%></a>
+% }
+% }
+% }
+</ul>
+</td>
+</tr>
+<%ARGS>
+$ArticleObj => undef
+$id => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/EditTopics b/rt/share/html/Articles/Article/Elements/EditTopics
new file mode 100644
index 000000000..807360bf2
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/EditTopics
@@ -0,0 +1,147 @@
+%# 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 }}}
+<input type="hidden" name="EditTopics" value="1" />
+<select multiple size="10" name="Topics">
+<%perl>
+if (@Classes) {
+ $m->print("<optgroup label=\"Current classes (".join (' ',map {$_->Name} @Classes).")\">")
+ unless $OnlyThisClass;
+ $inTree->traverse(sub {
+ my $tree = shift;
+ my $topic = $tree->getNodeValue;
+ $m->print("<option value=\"".$topic->Id."\""
+ .(exists $topics{$topic->Id} ? " selected" : "").">"
+ .("&nbsp;" x ($tree->getDepth*5)).($topic->Name || loc("(no name)"))."</option>\n");
+ });
+}
+unless ($OnlyThisClass) {
+ my $class = $Classes[-1]->Id;
+ $otherTree->traverse(sub {
+ my $tree = shift;
+ my $topic = $tree->getNodeValue;
+ unless ($topic->ObjectId == $class) {
+ $class = $topic->ObjectId;
+ $m->print("</optgroup>\n");
+ my $c = RT::Class->new($session{'CurrentUser'});
+ $c->Load($topic->ObjectId);
+ $m->print("<optgroup label=\"".$c->Name."\">\n");
+ }
+ $m->print("<option value=\"".$topic->Id."\""
+ .(exists $topics{$topic->Id} ? " selected" : "").">"
+ .("&nbsp;" x ($tree->getDepth*5)).($topic->Name || loc("(no name)"))."</option>\n");
+ });
+</%perl>
+</optgroup>
+% }
+</select>
+
+<%INIT>
+use Tree::Simple;
+
+my $inClass = RT::Topics->new($session{'CurrentUser'});
+# global topics should always be available
+push @Classes,$RT::System unless grep { $_ == $RT::System } @Classes;
+$inClass->LimitToObject($_) for @Classes;
+$inClass->OrderByCols({FIELD => 'Name'});
+my $inTree = buildTree($inClass);
+
+my $otherClass = RT::Topics->new($session{'CurrentUser'});
+if (@Classes) {
+ $otherClass->Limit(FIELD => 'ObjectType', VALUE => 'RT::Class');
+ for (@Classes) {
+ $otherClass->Limit(FIELD => 'ObjectId', OPERATOR => '!=', VALUE => $_->Id);
+ }
+} else {
+ $otherClass->UnLimit;
+}
+my $otherTree = buildTree($otherClass);
+
+my $articleTopics = RT::ObjectTopics->new($session{'CurrentUser'});
+$articleTopics->LimitToObject($ArticleObj);
+my %topics;
+while (my $topicObj = $articleTopics->Next) {
+ $topics{$topicObj->Topic} = 1;
+}
+$topics{$_} = 1 for @Topics;
+
+sub buildTree {
+ my $query = shift;
+
+ use Tree::Simple;
+ my $tree = Tree::Simple->new(Tree::Simple->ROOT);
+ my %lookup = (0 => $tree);
+
+ my @todo;
+ while (my $topic = $query->Next) {
+ push @todo, $topic;
+ }
+
+ {
+ my $changed = 0;
+ my @work = @todo;
+ @todo = ();
+ for my $topic (@work) {
+ if (defined $lookup{$topic->Parent}) {
+ $lookup{$topic->Id} = Tree::Simple->new($topic, $lookup{$topic->Parent});
+ $changed = 1;
+ } else {
+ push @todo, $topic;
+ }
+ }
+ redo unless $changed == 0;
+ }
+ return $tree;
+}
+
+</%INIT>
+<%ARGS>
+$ArticleObj => RT::Article->new($session{'CurrentUser'})
+@Classes => ()
+@Topics => ()
+$OnlyThisClass => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/LinkEntryInstructions b/rt/share/html/Articles/Article/Elements/LinkEntryInstructions
new file mode 100644
index 000000000..c2fd1efed
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/LinkEntryInstructions
@@ -0,0 +1,49 @@
+%# 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 }}}
+<&|/l&>Type <b>a:</b> before article numbers and <b>t:</b> before ticket numbers.</&>
+<&|/l&>Separate multiple entries with spaces.</&>
diff --git a/rt/share/html/Articles/Article/Elements/Preformatted b/rt/share/html/Articles/Article/Elements/Preformatted
new file mode 100644
index 000000000..2f0e7869e
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/Preformatted
@@ -0,0 +1,127 @@
+%# 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 }}}
+% if ($include{Name}) {
+#<%$Article->Id%>: <%$Article->Name || loc('(no name)')%>
+<%'-' x length("#".$Article->Id.": ".($Article->Name || loc('(no name)'))) %>
+% }
+% if ( $include{Summary} && ($Article->Summary||'') =~ /\S/ ) {
+<% $Article->Summary %>
+% }
+% while (my $cf = $cfs->Next) {
+% next unless $include{"CF-Title-".$cf->Id} or $include{"CF-Value-".$cf->Id};
+% my $values = $Article->CustomFieldValues($cf->Id);
+% if ($values->Count == 1) {
+% my $value = $values->First;
+% if ($include{"CF-Title-".$cf->Id}) {
+<% $cf->Name%>:
+<% '-' x length($cf->Name) %>
+% }
+% if ($value && $include{"CF-Value-".$cf->Id}) {
+<% $get_content->( $value ) %>
+% }
+% } else {
+% my $val = $values->Next;
+% if ($include{"CF-Title-".$cf->Id}) {
+<% $cf->Name%>: \
+% }
+% if ($val && $include{"CF-Value-".$cf->Id}) {
+<% $get_content->( $val ) %>
+% }
+% while ($val = $values->Next) {
+% if ($include{"CF-Title-".$cf->Id}) {
+<% ' ' x length($cf->Name)%> \
+% }
+% if ($include{"CF-Value-".$cf->Id}) {
+<% $get_content->( $val ) %>
+% }
+% }
+% }
+% }
+<%init>
+my $class = $Article->ClassObj;
+my %include = (Name => 1, Summary => 1);
+my $cfs = $class->ArticleCustomFields;
+$include{"CF-Title-".$_->Id} = $include{"CF-Value-".$_->Id} = 1 while $_ = $cfs->Next;
+$include{$_} = not $class->FirstAttribute("Skip-$_") for keys %include;
+
+my $de_htmlify = sub {
+ my $content = shift;
+ require HTML::TreeBuilder;
+ my $tree = HTML::TreeBuilder->new;
+ $tree->parse($content);
+ $tree->eof();
+
+ require HTML::FormatText;
+ my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 50);
+ $content = $formatter->format($tree);
+ return $content;
+};
+
+my $get_content = sub {
+ my $value = shift;
+ return '' unless $value;
+
+ my $content = $value->Content;
+ return '' unless defined $content && length $content;
+
+ $m->callback(
+ %ARGS,
+ CallbackName => 'ProcessContent',
+ content => \$content,
+ );
+
+ if ( $content =~ /<.{1,5}>/ ) {
+ $content = $de_htmlify->( $content );
+ }
+ return $content;
+};
+
+</%init>
+<%args>
+$Article
+</%args>
diff --git a/rt/share/html/Articles/Article/Elements/SearchByCustomField b/rt/share/html/Articles/Article/Elements/SearchByCustomField
new file mode 100644
index 000000000..2a9d14506
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/SearchByCustomField
@@ -0,0 +1,70 @@
+%# 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 }}}
+%# if the custom field is a select, enumerate the options
+% if ($Field->Type =~ /^Select/) {
+% my $CustomFieldValues = $Field->ValuesObj();
+<select name="<%$Name%>" size="5" multiple>
+% while (my $value = $CustomFieldValues->Next) {
+% my $name = $value->Name || '';
+<option value="<% $name %>" <% grep($_ eq $name, @Values)? 'SELECTED' : ''%>><% $name %></option>
+% }
+<option value="" <% $#Values < 0 && 'SELECTED'%>><&|/l&>(no value)</&></option>
+</select>
+% }
+%# otherwise, put in a textedity field
+% else {
+<input name="<%$Name%>" value="<%$Values[0]||''%>" />
+% }
+<%init>
+my @Values =ref( $Values ) ? @{ $Values } : ( $Values );
+</%init>
+<%ARGS>
+$Field => undef
+$Name => 'CustomField'
+$Values => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/SelectSavedSearches b/rt/share/html/Articles/Article/Elements/SelectSavedSearches
new file mode 100644
index 000000000..c42fae1b5
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/SelectSavedSearches
@@ -0,0 +1,76 @@
+%# 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 }}}
+<select name="<%$Name%>">
+% foreach my $privacy (reverse sort keys %privacies) {
+% my $searches = RT::SavedSearches->new($session{'CurrentUser'});
+% $searches->LimitToPrivacy($privacy, 'Article');
+% next unless $searches->Count;
+% if ($privacy =~ /^RT::User/) {
+<option value=""><&|/l&>My saved searches</&></option>
+% } else {
+<option value=""><&|/l, $privacies{$privacy}->Name&>[_1]'s saved searches</&></option>
+% }
+% while (my $search = $searches->Next) {
+% my $optionval = "$privacy-SavedSearch-". $search->Id;
+<option value="<%$optionval%>"<% $optionval eq $Default ? 'selected' : '' %>> - <%$search->Name||loc('Unnamed search')%></option>
+% }
+% }
+</select>
+
+<%init>
+use RT::SavedSearches;
+my $groups = $session{'CurrentUser'}->UserObj->OwnGroups;
+my %privacies;
+$privacies{'RT::User-' . $session{'CurrentUser'}->UserObj->Id} = 1;
+map { $privacies{'RT::Group-'.$_->Id} = $_ } @{$groups->ItemsArrayRef};
+</%init>
+
+<%args>
+$Name => undef
+$Default => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/Elements/SelectSearchPrivacy b/rt/share/html/Articles/Article/Elements/SelectSearchPrivacy
new file mode 100644
index 000000000..674a0ffa7
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/SelectSearchPrivacy
@@ -0,0 +1,62 @@
+%# 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 }}}
+<select name="<%$Name%>">
+<option value="RT::User-<% $user->Id %>" <% $Default eq 'RT::User-'.$user->Id ? 'selected' : '' %>>My searches</option>
+% while (my $group = $groups->Next) {
+<option value="RT::Group-<% $group->Id %>" <% $Default eq 'RT::Group-'.$group->Id ? 'selected' : '' %>><% $group->Name %>'s searches</option>
+% }
+</select>
+<%INIT>
+my $user = $session{'CurrentUser'}->UserObj;
+my $groups = $session{'CurrentUser'}->UserObj->OwnGroups;
+$Default = '' unless defined $Default;
+</%INIT>
+<%ARGS>
+$Name => 'GroupField'
+$Default => ''
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/ShowHistory b/rt/share/html/Articles/Article/Elements/ShowHistory
new file mode 100644
index 000000000..6ca74bf61
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/ShowHistory
@@ -0,0 +1,76 @@
+%# 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 }}}
+<table width="100%" cellspacing="0" cellpadding="2">
+% my $i;
+% while (my $transaction = $transactions->Next) {
+<tr class="<% ($i++)%2 ? 'oddline' : 'evenline'%>" >
+<td width="20%"><small><%$transaction->CreatedObj->AsString%></small></td>
+<td><%$transaction->CreatorObj->Name%></td>
+<td><%$transaction->Description%></td>
+</tr>
+% }
+</table>
+<%init>
+
+my $article = RT::Article->new($session{'CurrentUser'});
+
+$article->Load($id);
+unless ($article->Id) {
+ $m->comp("/Elements/Error", Why => loc("Article not found"));
+}
+
+unless ($article->ClassObj->CurrentUserHasRight('ShowArticle')) {
+ $m->comp("/Elements/Error", Why => loc("Permission Denied"));
+}
+
+my $transactions = $article->Transactions();
+
+</%init>
+<%args>
+$id => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/Elements/ShowLinks b/rt/share/html/Articles/Article/Elements/ShowLinks
new file mode 100644
index 000000000..2e48ac949
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/ShowLinks
@@ -0,0 +1,92 @@
+%# 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 }}}
+<span class="label"><&|/l&>Refers to</&></span>:<br />
+<ul class="value">
+% my $refersto = $article->RefersTo;
+
+% while (my $link = $refersto->Next) {
+% my $member = $link->TargetURI;
+<li>
+% if ($link->TargetURI->IsLocal) {
+<a href="<%$member->Resolver->HREF%>"><% loc($member->Object->ObjectTypeStr) %> <%$member->Object->Id%>:
+% if (UNIVERSAL::isa($member->Object, "RT::Article") or UNIVERSAL::can($member->Object, 'Name')) {
+<%$member->Object->Name%>
+% } elsif (UNIVERSAL::isa($member->Object, "RT::Ticket") or UNIVERSAL::can($member->Object, 'Subject')) {
+<%$member->Object->Subject%>
+% }
+</a>
+% } else {
+<a href="<%$member->Resolver->HREF%>"><%$link->Target%></a>
+% }
+</li>
+% }
+</ul>
+
+<span class="label"><&|/l&>Referred to by</&></span>:<br />
+<ul class="value">
+% my $referredtoby = $article->ReferredToBy;
+% while (my $link = $referredtoby->Next) {
+% my $member = $link->BaseURI;
+<li>
+% if ($member->IsLocal) {
+<a href="<%$member->Resolver->HREF%>"><% loc($member->Object->ObjectTypeStr) %> <%$member->Object->Id%>:
+% if (UNIVERSAL::isa($member->Object, "RT::Article") or UNIVERSAL::can($member->Object, 'Name')) {
+<%$member->Object->Name%>
+% } elsif (UNIVERSAL::isa($member->Object, "RT::Ticket") or UNIVERSAL::can($member->Object, 'Subject')) {
+<%$member->Object->Subject%>
+% }
+</a>
+% } else {
+<a href="<%$member->Resolver->HREF%>"><%$link->Base%></a>
+% }
+</li>
+% }
+</ul>
+<%args>
+$article => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/Elements/ShowSavedSearches b/rt/share/html/Articles/Article/Elements/ShowSavedSearches
new file mode 100644
index 000000000..8ced74b1c
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/ShowSavedSearches
@@ -0,0 +1,85 @@
+%# 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/TitleBoxStart, title => loc('Saved searches') &>
+%# Keep track of what our current search ID is.
+<input type="hidden" name="CurrentSearch" value="<% $CurrentSearch ? $CurrentSearch : 'new' %>">
+%# Hide all the save functionality if the user shouldn't see it.
+% if ($session{'CurrentUser'}->HasRight( Right => 'CreateSavedSearch',
+% Object=> $RT::System )) {
+<h2><&|/l&>Save this search</&></h2>
+<&|/l&>Name:</&> <input name="NewSearchName" value="<%$Name||''%>">
+<&|/l&>Privacy:</&> <& SelectSearchPrivacy, Name => 'SearchPrivacy',
+ Default => $Privacy &><br />
+% if ($CurrentSearch && $CurrentSearch ne 'new') {
+<input value="<%loc('Update')%>" name="Update" type="submit" />&nbsp;
+<input value="<%loc('Save new')%>" name="Save" type="submit" />&nbsp;
+<input value="<%loc('Delete')%>" name="Delete" type="submit" />&nbsp;
+% } else {
+<input value="<%loc('Save')%>" name="Save" type="submit" />
+% }
+<hr />
+% } # if HasRight 'CreateSavedSearch'
+
+<h2><&|/l&>Load a saved search</&></h2>
+<& SelectSavedSearches, Name => 'LoadSavedSearch', Default => $CurrentSearch &>
+<input value="<%loc('Load')%>" name="Load" type="submit">
+<& /Elements/TitleBoxEnd &>
+
+<%INIT>
+unless ($session{'CurrentUser'}->HasRight( Right => 'LoadSavedSearch',
+ Object=> $RT::System )) {
+ return;
+}
+
+</%INIT>
+
+<%ARGS>
+$CurrentSearch => undef
+$Name => undef
+$Privacy => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/ShowSearchCriteria b/rt/share/html/Articles/Article/Elements/ShowSearchCriteria
new file mode 100644
index 000000000..377cdb1f0
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/ShowSearchCriteria
@@ -0,0 +1,171 @@
+%# 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 }}}
+% if ($ARGS{'HideOptions'}) {
+<& /Elements/TitleBoxStart, title => loc('Advanced search'), class => "rolled-up", bodyclass => "hidden" &>
+% } else {
+<& /Elements/TitleBoxStart, title => loc('Advanced search') &>
+% }
+<table>
+<tr>
+<td class="label" colspan="2"><h2><&|/l&>Basics</&></h2></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Class</&></td><td class="value">is <& /Articles/Elements/SelectClass, Name => 'Class', Multiple =>1, Size => 5 , ShowNullOption => undef, Default => $ARGS{'Class'} &>
+<&|/l&>and not</&>
+<& /Articles/Elements/SelectClass, Name => 'Class!', Multiple =>1, Size => 5 , ShowNullOption => undef, Default => $ARGS{'Class!'} &></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Name</&></td>
+<td class="value"><&|/l&>matches</&> <input name="Name~" value="<%$ARGS{'Name~'}%>" /> <&|/l&>and not</&> <input name="Name!~" value="<%$ARGS{'Name!~'}%>" /></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Summary</&></td>
+<td class="value"><&|/l&>matches</&> <input name="Summary~" value="<%$ARGS{'Summary~'}%>" /> <&|/l&>and not</&> <input name="Summary!~" value="<%$ARGS{'Summary!~'}%>" /></td>
+</tr>
+<tr>
+<td class="label" colspan="2"><h2><&|/l&>Content</&></h2></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Any field</&></td><td class="value"> <&|/l&>matches</&> <input name="Article~" value="<%$ARGS{'Article~'}%>" /> <&|/l&>and not</&> <input name="Article!~" value="<%$ARGS{'Article!~'}%>" /></td>
+</tr>
+% while (my $field = $customfields->Next ) {
+<tr>
+<td class="label"><% $field->Name %></td>
+<td class="value"><&|/l&>matches</&>
+% my $matches = $field->Name."~";
+% my $nomatches = $field->Name."!~";
+<& /Articles/Article/Elements/SearchByCustomField,
+ Field => $field,
+ Name => $matches,
+ Values => $ARGS{$matches} &>
+ <&|/l&>and not</&>
+<& /Articles/Article/Elements/SearchByCustomField,
+ Field => $field,
+ Name => $nomatches,
+ Values => $ARGS{$nomatches}
+ &>
+</td>
+</tr>
+% }
+<tr>
+<td class="label" colspan="2"><h2><&|/l&>Dates</&></h2></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Created</&></td>
+<td class="value"><&|/l&>after</&>
+<& /Elements/SelectDate, Name=>"Created>", Default => ($dates->{'Created>'} ? $dates->{'Created>'}->ISO : '') &>
+<&|/l&>and before</&>
+<& /Elements/SelectDate, Name=>"Created<", Default => ($dates->{'Created<'} ? $dates->{'Created<'}->ISO:'')&>
+</td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Last updated</&></td>
+<td class="value"><&|/l&>after</&>
+<& /Elements/SelectDate, Name=>"LastUpdated>", Default =>
+($dates->{'LastUpdated>'} ? $dates->{'LastUpdated>'}->AsString:'')&>
+<&|/l&>and before</&>
+<& /Elements/SelectDate, Name=>"LastUpdated<", Default =>
+($dates->{'LastUpdated<'} ? $dates->{'LastUpdated<'}->AsString:'')&>
+</td>
+</tr>
+<tr>
+<td class="label" colspan="2"><h2><&|/l&>Links</&></h2></td>
+</tr>
+<tr>
+<td class="label"></td>
+<td><& LinkEntryInstructions &></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Refer to</&></td>
+<td class="value"><input type=text size=50 name="RefersTo" value="<%$RefersTo%>" /></td>
+</tr>
+<tr>
+<td class="label"><&|/l&>Referred to by</&></td>
+<td class="value"><input type=text size=50 name="ReferredToBy" value="<%$ReferredToBy%>" /></td>
+</tr>
+<tr>
+<td class="label" colspan="2"><h2><&|/l&>Topics</&></h2></td>
+</tr>
+<tr>
+<td class="label"></td>
+<td>
+<& /Articles/Article/Elements/EditTopics, %ARGS, Classes => \@Classes, OnlyThisClass => 1 &>
+<br />
+<input type="checkbox" name="ExpandTopics" <% $ARGS{'ExpandTopics'} ? 'checked="checked"' : "" %> />
+<&|/l&>Include subtopics</&>
+</td>
+</tr>
+</table>
+<& /Elements/Submit, Label => loc('Search') &>
+<&/Elements/TitleBoxEnd&>
+<%init>
+my @Classes =
+ ( ref $ARGS{'Class'} eq 'ARRAY' )
+ ? @{ $ARGS{'Class'} }
+ : ( $ARGS{'Class'} );
+for (@Classes) {
+ my $class = RT::Class->new( $session{'CurrentUser'} );
+ $class->LoadById($_);
+ $_ = $class;
+}
+
+for my $field ( qw/Class Name Summary Article/ ) {
+ $ARGS{"$field~"} = '' unless defined $ARGS{"$field~"};
+ $ARGS{"$field!~"} = '' unless defined $ARGS{"$field!~"};
+}
+$RefersTo = '' unless defined $RefersTo;
+$ReferredToBy = '' unless defined $ReferredToBy;
+
+</%init>
+
+<%ARGS>
+$dates =>undef
+$RefersTo => ''
+$ReferredToBy => ''
+$customfields => undef
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/Elements/ShowTopics b/rt/share/html/Articles/Article/Elements/ShowTopics
new file mode 100644
index 000000000..31aae36eb
--- /dev/null
+++ b/rt/share/html/Articles/Article/Elements/ShowTopics
@@ -0,0 +1,58 @@
+%# 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 }}}
+% my $topics = RT::ObjectTopics->new($session{'CurrentUser'});
+% $topics->LimitToObject($article);
+% my @topics;
+% while (my $t = $topics->Next) {
+<& /Articles/Elements/ShowTopic, topic => $t->TopicObj &><br />
+% }
+<br />
+
+<%args>
+$article => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/ExtractFromTicket.html b/rt/share/html/Articles/Article/ExtractFromTicket.html
new file mode 100644
index 000000000..5d9eba2fc
--- /dev/null
+++ b/rt/share/html/Articles/Article/ExtractFromTicket.html
@@ -0,0 +1,105 @@
+%# 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('Extract article from ticket #[_1] into class [_2]',$Ticket, $ClassObj->Name) &>
+<& /Elements/Tabs &>
+<form action="Edit.html" method="post">
+<input type="hidden" name="Class" value="<%$ARGS{'Class'}%>" />
+<input type="hidden" name="Summary" value="<%$ticket->Subject%>" />
+% for (@Topics) {
+<input type="hidden" name="Topics" value="<% $_ %>" />
+% }
+<input type="hidden" name="new-RefersTo" value="t:<% $ticket->id%>" />
+<table width="100%" valign="top" border=0 cellspacing=0>
+<p><&|/l&>Use the dropdown menus to select which ticket updates you want to extract into a new article.</&>
+<&|/l&>You can insert ticket content into any freeform, text or wiki field.</&>
+</p>
+<tr>
+<th><&|/l&>Field</&></th>
+<th><&|/l&>Ticket update</&></th>
+</tr>
+% my $i;
+% while ( my $trans = $transactions->Next ) {
+% next unless $trans->Content;
+<tr class="<% ($i++)%2 ? 'oddline' : 'evenline'%>" >
+<td valign="top">
+<select name="Transaction-<%$trans->Id%>">
+<option value="">-</option>
+% while (my $cf = $CustomFields->Next) {
+<option value="<%$cf->Id%>"><%$cf->Name%></option>
+% }
+</select>
+</td>
+<td><b><%$trans->CreatedObj->AsString%>: <%$trans->Description%></b><br />
+<pre><%$trans->Content%></pre>
+</td>
+</tr>
+% }
+</table>
+<& /Elements/Submit, Label => loc('Create'), color => "#993333" &>
+</form>
+<%INIT>
+
+my $ticket=LoadTicket($Ticket);
+my $transactions = $ticket->Transactions;
+
+my $ClassObj = RT::Class->new($session{'CurrentUser'});
+$ClassObj->Load($Class);
+unless ($ClassObj->Id) {
+ $m->comp("/Elements/Error", Why => loc("'[_1]' isn't a valid class identifier", $Class));
+}
+my $CustomFields = $ClassObj->ArticleCustomFields();
+
+$CustomFields->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => 'Text');
+$CustomFields->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => 'Wikitext');
+$CustomFields->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => 'Freeform');
+</%init>
+<%ARGS>
+$Class => undef
+$Ticket => undef
+@Topics => ()
+</%ARGS>
diff --git a/rt/share/html/Articles/Article/ExtractIntoClass.html b/rt/share/html/Articles/Article/ExtractIntoClass.html
new file mode 100644
index 000000000..adf23fc0f
--- /dev/null
+++ b/rt/share/html/Articles/Article/ExtractIntoClass.html
@@ -0,0 +1,76 @@
+%# 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('Extract a new article from ticket #[_1]',$Ticket) &>
+<& /Elements/Tabs &>
+
+
+<h2><&|/l&>Create a new article in</&>:</h2>
+<ul>
+% my $Classes = RT::Classes->new($session{'CurrentUser'});
+% $Classes->LimitToEnabled();
+% while (my $Class = $Classes->Next) {
+<li><a href="ExtractIntoTopic.html?Ticket=<%$Ticket%>&Class=<%$Class->Id%>" onclick="document.getElementById('topics-<% $Class->Id %>').style.display = (document.getElementById('topics-<% $Class->Id %>').style.display == 'block') ? 'none' : 'block'; return false;"><%$Class->Name%></a>:
+<%$Class->Description%>
+<div id="topics-<%$Class->Id%>" style="display: none">
+<form action="ExtractFromTicket.html">
+<input type="hidden" name="Ticket" value="<% $Ticket %>" />
+<input type="hidden" name="Class" value="<% $Class->id %>" />
+<&|/l &>Select topics for this article</&>:<br />
+<& Elements/EditTopics, Classes => [$Class],
+ OnlyThisClass => 1,
+ id => 'new',
+ &><br />
+<input type="submit" value="<%loc('Create')%>" />
+</form>
+<br /></div>
+</li>
+% }
+</ul>
+<%args>
+$Ticket => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/ExtractIntoTopic.html b/rt/share/html/Articles/Article/ExtractIntoTopic.html
new file mode 100644
index 000000000..72fd32464
--- /dev/null
+++ b/rt/share/html/Articles/Article/ExtractIntoTopic.html
@@ -0,0 +1,72 @@
+%# 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('Extract a new article from ticket #[_1]',$Ticket) &>
+<& /Elements/Tabs &>
+
+
+<&|/l&>Select topics for this article</&>:<br />
+<form action="ExtractFromTicket.html">
+<input type="hidden" name="Ticket" value="<% $Ticket %>" />
+<input type="hidden" name="Class" value="<% $ClassObj->id %>" />
+<& Elements/EditTopics, Classes => [$ClassObj],
+ OnlyThisClass => 1,
+ id => 'new',
+ &><br />
+<input type="submit" value="<%loc('Create')%>" />
+</form>
+<%args>
+$Ticket => undef
+$Class => undef
+</%args>
+<%init>
+my $ClassObj = RT::Class->new($session{'CurrentUser'});
+$ClassObj->Load($Class);
+unless ($ClassObj->Id) {
+ $m->comp("/Elements/Error", Why => loc("'[_1]' isn't a valid class identifier", $Class));
+}
+</%init>
diff --git a/rt/share/html/Articles/Article/History.html b/rt/share/html/Articles/Article/History.html
new file mode 100644
index 000000000..1c2873f18
--- /dev/null
+++ b/rt/share/html/Articles/Article/History.html
@@ -0,0 +1,57 @@
+%# 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 => $title &>
+<& /Elements/Tabs &>
+<& Elements/ShowHistory, id => $id &>
+<%init>
+my $title =loc('History for article #[_1]',$id);
+</%init>
+
+<%args>
+$id => undef
+</%args>
diff --git a/rt/share/html/Articles/Article/PreCreate.html b/rt/share/html/Articles/Article/PreCreate.html
new file mode 100644
index 000000000..49507d4a8
--- /dev/null
+++ b/rt/share/html/Articles/Article/PreCreate.html
@@ -0,0 +1,62 @@
+%# 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('Create an article in class...') &>
+<& /Elements/Tabs, Title => loc('Create an article in class...') &>
+<ul>
+% my $Classes = RT::Classes->new($session{'CurrentUser'});
+% $Classes->LimitToEnabled();
+% my $have_classes = 0;
+% while (my $Class = $Classes->Next) {
+% $have_classes++;
+% my $qs = $m->comp("/Elements/QueryString", %ARGS, Class=> $Class->Id);
+<li><a href="Edit.html?<% $qs|n %>"><&|/l, $Class->Name &>in class [_1]</&></a></li>
+% }
+</ul>
+% unless ( $have_classes ) {
+<span><&|/l&>Permission Denied</&></span>
+% }
diff --git a/rt/share/html/Articles/Article/Search.html b/rt/share/html/Articles/Article/Search.html
new file mode 100644
index 000000000..f995d41a7
--- /dev/null
+++ b/rt/share/html/Articles/Article/Search.html
@@ -0,0 +1,269 @@
+%# 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("Search for articles") &>
+<& /Elements/Tabs &>
+
+% unless ( keys %ARGS ) {
+% my $Classes = RT::Classes->new($session{'CurrentUser'});
+% $Classes->LimitToEnabled();
+<table width="100%" border="0">
+<tr>
+<td valign="top" width="50%">
+<ul>
+% while (my $class = $Classes->Next) {
+<li><a href="<%RT->Config->Get('WebPath')%>/Articles/Article/Search.html?<% $m->comp('/Elements/QueryString', %filtered, Class => $class->id) %>"><&|/l, $class->Name&>in class [_1]</&></a></li>
+% }
+</ul>
+</td>
+<td valign="top" width="50%">
+<form action="Search.html" method="get">
+<& /Elements/TitleBoxStart, title => loc('Saved searches') &>
+<&|/l&>Load saved search:</&><br />
+<& Elements/SelectSavedSearches, Name => 'LoadSavedSearch', Default => $CurrentSearch &>
+<input value="<%loc('Load')%>" name="Load" type="submit" />
+<& /Elements/TitleBoxEnd &>
+</form>
+</td>
+</tr>
+</table>
+% return;
+% }
+
+<& /Elements/ListActions, actions => \@results &>
+<div style="float: right"><a href="#criteria"><&|/l&>Modify this search...</&></a></div>
+
+% if ($articles->BuildSelectCountQuery =~ /WHERE/i) {
+<h2><&|/l&>Search results</&></h2>
+<& /Elements/CollectionList,
+ Collection => $articles,
+ AllowSorting => 1,
+ OrderBy => \@OrderBy,
+ Order => \@Order,
+ Format => $format,
+ GenericQueryArgs => { %filtered, Format => $format, },
+ &>
+% }
+
+<br />
+<br />
+<br />
+<a name="criteria"></a>
+<form action="Search.html" method="get">
+<& Elements/ShowSearchCriteria, dates => \%dates, RefersTo => $RefersTo, customfields => $customfields, ReferredToBy => $ReferredToBy, %ARGS &>
+<br />
+<br />
+<& Elements/ShowSavedSearches, CurrentSearch => $CurrentSearch,
+ Name => ($search ? $search->Name : undef),
+ Privacy => ($search ? $search->Privacy : undef) &>
+
+</form>
+
+<div align=right>
+<a href="<%RT->Config->Get('WebPath')%>/Articles/Article/Search.html<%$QueryString%>"><&|/l&>Bookmarkable link for this search</&></a><br />
+</div>
+<%init>
+use RT::SavedSearch;
+my @results;
+my $articles = RT::Articles->new( $session{'CurrentUser'} );
+my $format = q{
+ '<a href="__WebPath__/Articles/Article/Display.html?id=__id__">__id__</a>/TITLE:#',
+ '<a href="__WebPath__/Articles/Article/Display.html?id=__id__">__Name__</a>/TITLE:Name',
+ '__ClassName__',
+ '__CreatedRelative__',
+ '__LastUpdatedRelative__',
+ '__Summary__',
+ '__Topics__', };
+
+# {{{ Quicksearch logic
+
+# If it is a number, load the article with that ID. Otherwise, search
+# on name and summary.
+if ($ARGS{'q'} && $ARGS{'q'} =~ /^(\d+)$/) {
+ return $m->comp("/Articles/Article/Display.html", id => $1);
+}
+# }}}
+
+# {{{ Saved search logic
+
+my $search;
+
+# The keys in %ARGS that are not saved and loaded with named searches.
+# These need to be treated specially.
+my @metakeys = qw/NewSearchName CurrentSearch SearchPrivacy Save Load
+ Update Delete/;
+
+if ($CurrentSearch =~ /^(.*-\d+)-SavedSearch-(\d+)$/) {
+ $search = RT::SavedSearch->new($session{'CurrentUser'});
+ $search->Load($1, $2);
+}
+
+# Have we been asked to load a search?
+
+if ($ARGS{'Load'}) {
+ if ($ARGS{'LoadSavedSearch'} =~ /^(.*-\d+)-SavedSearch-(\d+)$/ ) {
+ my $privacy = $1;
+ my $search_id = $2;
+
+ $search = RT::SavedSearch->new($session{'CurrentUser'});
+ my ($ret, $msg) = $search->Load($privacy, $search_id);
+ if ($ret) {
+ my $searchargs = $search->GetParameter('args');
+ # Clean out ARGS and fill it in with the saved args from the
+ # loaded search.
+ foreach my $key (@metakeys) {
+ $searchargs->{$key} = $ARGS{$key};
+ }
+ %ARGS = %{$searchargs};
+ $CurrentSearch = "$privacy-SavedSearch-$search_id";
+ } else {
+ push(@results, loc("Error: could not load saved search [_1]: [_2]",
+ $ARGS{'LoadSavedSearch'}, $msg));
+ }
+ } else {
+ push(@results, loc("Invalid [_1] argument", 'LoadSavedSearch'));
+ }
+}
+
+# ...or have we been asked to save, update, or delete a search?
+
+if ($ARGS{'Save'}) {
+ my %searchargs = %ARGS;
+ foreach my $key (@metakeys) {
+ delete $searchargs{$key};
+ }
+
+ $search = RT::SavedSearch->new($session{'CurrentUser'});
+ unless ($ARGS{'SearchPrivacy'} =~ /^(.*)-(\d+)$/) {
+ # This shouldn't really happen, but hey.
+ push(@results, loc("WARNING: Saving search to user-level privacy"));
+ $ARGS{'SearchPrivacy'} = 'RT::User-'.$session{'CurrentUser'}->Id;
+ }
+ my ($ret, $msg) = $search->Save(Privacy => $ARGS{'SearchPrivacy'},
+ Type => 'Article',
+ Name => $ARGS{'NewSearchName'},
+ SearchParams => {'args' => \%searchargs});
+ if ($ret) {
+ $CurrentSearch = $ARGS{'SearchPrivacy'} . "-SavedSearch-" .
+ $search->Id;
+ push(@results, loc("Created search [_1]", $search->Name));
+ } else {
+ undef $search; # if we bomb out creating a search
+ # we don't want to have the empty object hang around
+ push(@results, loc("Could not create search: [_1]", $msg));
+ }
+} elsif ($ARGS{'Update'}) {
+ if ($ARGS{'SearchPrivacy'} != $search->Privacy) {
+ push(@results,
+ loc("Error: cannot change privacy value of existing search"));
+ } else {
+ my %searchargs = %ARGS;
+ foreach my $key (@metakeys) {
+ delete $searchargs{$key};
+ }
+
+ # We already have a search loaded, because CurrentSearch is set,
+ # or else we would not have gotten here.
+ my ($ret, $msg) = $search->Update(Name => $ARGS{'NewSearchName'},
+ SearchParams => \%searchargs);
+ if ($ret) {
+ push(@results, loc("Search [_1] updated", $search->Name));
+ } else {
+ push(@results, loc("Error: search [_1] not updated: [_2]",
+ $search->Name, $msg));
+ }
+ }
+} elsif ($ARGS{'Delete'}) {
+ # Keep track of this, as we are about to delete the search.
+ my $searchname = $search->Name;
+ my ($ret, $msg) = $search->Delete;
+ if ($ret) {
+ $ARGS{'CurrentSearch'} = undef;
+ push(@results, loc("Deleted search [_1]", $searchname));
+ # Get rid of all the state.
+ foreach my $key (keys %ARGS) {
+ delete $ARGS{$key};
+ }
+ $CurrentSearch = 'new';
+ $search = undef;
+ $RefersTo = undef;
+ $ReferredToBy = undef;
+ } else {
+ push(@results, loc("Could not delete search [_1]: [_2]",
+ $searchname, $msg));
+ }
+}
+
+# }}}
+
+ # Don't want to search for a null class when there is no class specced
+my $customfields = RT::CustomFields->new( $session{'CurrentUser'} );
+my %dates;
+
+$articles->Search( %ARGS, CustomFields => $customfields, Dates => \%dates,
+ OrderBy => \@OrderBy, Order => \@Order, );
+
+$m->callback( %ARGS, _Search => $articles );
+
+my %filtered = %ARGS;
+delete $filtered{$_} for (@metakeys, "EditTopics", "ExpandTopics");
+delete $filtered{$_} for grep {$filtered{$_} !~ /\S/} keys %filtered;
+@filtered{qw(OrderBy Order)} = (\@OrderBy, \@Order);
+my $QueryString = "?".$m->comp('/Elements/QueryString', %filtered);
+</%init>
+
+<%ARGS>
+$CreatedBefore => ''
+$CreatedAfter => ''
+$LastUpdatedBefore => ''
+$LastUpdatedAfter => ''
+$RefersTo => undef
+$ReferredToBy => undef
+$CurrentSearch => 'new'
+@OrderBy => ()
+@Order => ()
+</%ARGS>
diff --git a/rt/share/html/Articles/Elements/BeforeMessageBox b/rt/share/html/Articles/Elements/BeforeMessageBox
new file mode 100644
index 000000000..8ed04513f
--- /dev/null
+++ b/rt/share/html/Articles/Elements/BeforeMessageBox
@@ -0,0 +1,239 @@
+%# 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 }}}
+% if ( $ARGS{id} && $ARGS{id} ne 'new' ) {
+<input type="hidden" name="<%$ARGS{'id'}%>-RefersTo" value="<% join(' ',grep {$_} sort keys %uri) %>" />
+% }
+
+<table class="articles-select-article">
+% unless (RT->Config->Get('HideArticleSearchOnReplyCreate')) {
+<tr>
+<td><&|/l&>Search for Articles matching</&></td>
+<td><input size=20 name="<% $name_prefix %>Articles_Content" /></td>
+</tr>
+<tr>
+<td><&|/l&>Include Article:</&></td>
+<td><input size=20 name="<% $name_prefix %>Articles-Include-Article-Named" /></td>
+<td><input type="submit" name="Go" value="Go" /></td>
+</tr>
+% }
+% if ($hotlist->Count) {
+<tr>
+<td><&|/l&>Select an Article to include</&></td>
+<td><select name="<% $name_prefix %>Articles-Include-Article-Named-Hotlist" onchange="this.form.submit()">
+<option value="" selected><&|/l&>-</&></option>
+% while (my $article = $hotlist->Next) {
+<option value="<% $article->Id %>"><%$article->Name|| loc('(no name)')%>: <%$article->Summary || ''%></option>
+% }
+</select>
+</td>
+<td><input type="submit" name="Go" value="Go" /></td>
+</tr>
+% }
+% my %dedupe_articles;
+% while (my $article = $articles_content->Next) {
+% $dedupe_articles{$article->Id}++;
+<tr>
+<td>&nbsp;</td>
+<td><%$article->Name|| loc('(no name)')%>: <%$article->Summary%></td>
+<td><input type="submit" name="<% $name_prefix %>Articles-Include-Article-<%$article->Id%>" value="Go" /></td>
+</tr>
+% }
+% while (my $article = $articles_basics->Next) {
+% next if $dedupe_articles{$article->Id};
+<tr>
+<td>&nbsp;</td>
+<td><%$article->Name || loc('(no name)')%>: <%$article->Summary || ''%></td>
+<td><input type="submit" name="<% $name_prefix %>Articles-Include-Article-<%$article->Id%>" value="Go" /></td>
+</tr>
+% }
+% if ( @$topics ) {
+<tr>
+<td>
+<&|/l, $QueueObj->Name &>Choose from Topics for [_1]</&>
+</td>
+<td>
+<select name="<% $name_prefix %>Articles-Include-Topic" onchange="this.form.submit()">
+<option value="" selected>-</option>
+% for ( @$topics ) {
+<option value="<% $_->{id} %>"><%'&nbsp;' x $_->{depth} . ($_->{name}|| loc('(no name)')) |n%>
+</option>
+% }
+</select>
+</td>
+<td><input type="submit" name="Go" value="Go" /></td>
+</tr>
+
+% if ( $ARGS{$name_prefix .'Articles-Include-Topic'} ) {
+<tr>
+<td>
+<&|/l, $included_topic->Name &>Select an Article from [_1]</&>
+</td>
+<td>
+<select name="<% $name_prefix %>Articles-Include-Article" onchange="this.form.submit()">
+<option value="" selected>-</option>
+% while ( my $art = $topic_articles->Next ) {
+<option value="<% $art->id %>"><%$art->Name||loc('(no name)')%>: <%$art->Summary%></option>
+% }
+</select>
+</td>
+<td><input type="submit" value="Go" name="Go" /></td>
+</tr>
+
+% }
+% }
+
+
+</table>
+
+<%init>
+my $QueueObj = $ARGS{QueueObj};
+if ( $ARGS{id} && $ARGS{id} ne 'new' && !$QueueObj ) {
+ my $ticket = RT::Ticket->new( $session{CurrentUser} );
+ $ticket->Load( $ARGS{id} );
+ $QueueObj = $ticket->QueueObj;
+}
+
+my $skip = 0;
+$m->callback(CallbackName => "Init", skip => \$skip, Queue => $QueueObj);
+return if $skip;
+
+my $name_prefix = '';
+if ( $ARGS{'MessageBoxName'} ) {
+ $name_prefix = $ARGS{'MessageBoxName'} .'-';
+}
+
+# convert Articles-Include-Article => $id to Articles-Include-Article-$id
+if ( my $tmp = $ARGS{$name_prefix ."Articles-Include-Article"} ) {
+ $ARGS{$name_prefix ."Articles-Include-Article-$tmp"}++;
+}
+
+my %uri;
+if ( $ARGS{id} && $ARGS{id} ne 'new' ) {
+ $uri{$_}++ for split ' ', ($ARGS{$ARGS{'id'}.'-RefersTo'} || '');
+
+ foreach my $arg (keys %ARGS) {
+ next if $name_prefix && substr($arg, 0, length($name_prefix)) ne $name_prefix;
+
+ my $article = RT::Article->new($session{'CurrentUser'});
+ $article->LoadByInclude(
+ Field => substr($arg, length($name_prefix)),
+ Value => $ARGS{$arg},
+ );
+ if ($article->Id) {
+ $uri{$article->URI}++;
+ }
+ }
+}
+
+use RT::Articles;
+
+my $articles_content =
+ RT::Articles->new( $session{'CurrentUser'} );
+my $articles_basics = RT::Articles->new( $session{'CurrentUser'} );
+if ( my $tmp = $ARGS{ $name_prefix ."Articles_Content" } ) {
+ $articles_content->LimitCustomField(
+ VALUE => $tmp, OPERATOR => 'LIKE'
+ );
+ $articles_content->LimitAppliedClasses( Queue => $QueueObj );
+
+ $articles_basics->Limit( SUBCLAUSE => 'all',
+ FIELD => 'Name',
+ OPERATOR => 'LIKE',
+ VALUE => $tmp,
+ ENTRYAGGREGATOR => "OR" );
+ $articles_basics->Limit( SUBCLAUSE => 'all',
+ FIELD => 'Summary',
+ OPERATOR => 'LIKE',
+ VALUE => $tmp,
+ ENTRYAGGREGATOR => "OR" );
+ $articles_basics->LimitAppliedClasses( Queue => $QueueObj );
+}
+
+my $hotlist = RT::Articles->new( $session{'CurrentUser'} );
+$hotlist->LimitHotlistClasses;
+$hotlist->LimitAppliedClasses( Queue => $QueueObj );
+
+my ( $topic_articles, $topics, $included_topic );
+$topic_articles = RT::Articles->new( $session{CurrentUser} );
+$topics = [];
+
+my $top_topic = RT::Topic->new( $session{CurrentUser} );
+$top_topic->LoadByCols( Name => 'Queues', Parent => 0 , ObjectType => 'RT::System', ObjectId => 1);
+
+if ( $top_topic->id ) {
+ my $queue_topic = RT::Topic->new( $session{CurrentUser} );
+ $queue_topic->LoadByCols( Name => $QueueObj->Name, Parent => $top_topic->id );
+ if ( $queue_topic->id ) {
+
+ # store all topics below $queue_topic to $topics
+ topics( $queue_topic, $topics, 0 );
+
+ if ( my $tmp = $ARGS{ $name_prefix .'Articles-Include-Topic'} ) {
+ $included_topic = RT::Topic->new( $session{CurrentUser} );
+ $included_topic->Load( $tmp );
+ $topic_articles->LimitTopics( $tmp );
+ $topic_articles->OrderBy( FIELD => 'Name' );
+ }
+ }
+}
+
+
+# recursively get all the topics given a top topic
+sub topics {
+ my $parent = shift;
+ my $out = shift;
+ my $depth = shift;
+ while ( my $topic = $parent->Children->Next ) {
+ push @$out, { id => $topic->id, name => $topic->Name, depth => $depth };
+ topics( $topic, $out, $depth+1 );
+ }
+}
+
+</%init>
+
+
diff --git a/rt/share/html/Articles/Elements/CheckSkipCreate b/rt/share/html/Articles/Elements/CheckSkipCreate
new file mode 100644
index 000000000..6524f2615
--- /dev/null
+++ b/rt/share/html/Articles/Elements/CheckSkipCreate
@@ -0,0 +1,76 @@
+%# 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 }}}
+<%INIT>
+
+return if $checks_failure; # we're already skipping Create
+return unless RT->Config->Get('ArticleOnTicketCreate');
+
+
+my $article = RT::Article->new($session{'CurrentUser'});
+foreach my $arg ( keys %$ARGSRef) {
+
+ if ( $ARGSRef->{Articles_Content} || # search for an article
+ $ARGSRef->{'Articles-Include-Topic'} || # using Queue Topics
+ ( $article->LoadByInclude( Field => $arg, Value => $ARGSRef->{$arg} ) &&
+ $article->id ) ) { # including an article
+
+ $$skip_create = 1;
+ last;
+ }
+}
+return;
+
+</%INIT>
+
+<%ARGS>
+$ARGSRef => undef
+$skip_create => undef
+$checks_failure => undef
+$results => undef
+</%ARGS>
+
diff --git a/rt/share/html/Articles/Elements/CreateArticle b/rt/share/html/Articles/Elements/CreateArticle
new file mode 100644
index 000000000..effd50315
--- /dev/null
+++ b/rt/share/html/Articles/Elements/CreateArticle
@@ -0,0 +1,59 @@
+%# 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/TitleBoxStart, title => loc('Create an article') &>
+<ul>
+% while (my $Class = $Classes->Next) {
+<li><a href="Article/Edit.html?Class=<%$Class->Id%>"><%$Class->Name%></a></li>
+% }
+</ul>
+<& /Elements/TitleBoxEnd &>
+<%init>
+my $Classes = RT::Classes->new($session{'CurrentUser'});
+$Classes->LimitToEnabled;
+</%init>
+
diff --git a/rt/share/html/Articles/Elements/GotoArticle b/rt/share/html/Articles/Elements/GotoArticle
new file mode 100644
index 000000000..c8e5e5847
--- /dev/null
+++ b/rt/share/html/Articles/Elements/GotoArticle
@@ -0,0 +1,73 @@
+%# 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 }}}
+<form ACTION="<% RT->Config->Get('WebPath') %>/Articles/Article/Search.html">
+<input type="hidden" name="HideOptions" value="1" />
+<input size="12" name="q" accesskey="0" />
+% if ($class or $topic) {
+<input type="hidden" name="ExpandTopics" value="1" />
+<select name="Topics">
+% if ($topic) {
+<option value="<% $topic %>">in this topic</option>
+% }
+% if ($class) {
+% my $Topics = RT::Topics->new($session{'CurrentUser'});
+% $Topics->Limit(FIELD => 'ObjectType', VALUE => 'RT::Class');
+% $Topics->Limit(FIELD => 'ObjectId', VALUE => $class);
+% my @topics;
+% push @topics, $_->Id while $_ = $Topics->Next;
+<option value="<% join(' ', @topics) %>">in this hierarchy</option>
+% }
+<option value="">in all topics</option>
+</select>
+% }
+<input type="submit" value="<&|/l&>Search Articles</&>" />&nbsp;
+</form>
+<%args>
+$topic => ""
+$class => ""
+</%args>
diff --git a/rt/share/html/Articles/Elements/IncludeArticle b/rt/share/html/Articles/Elements/IncludeArticle
new file mode 100644
index 000000000..f19815f58
--- /dev/null
+++ b/rt/share/html/Articles/Elements/IncludeArticle
@@ -0,0 +1,99 @@
+%# 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 }}}
+<%INIT>
+
+my $parent_args = $m->caller_args(-1);
+
+my $name_prefix = '';
+$name_prefix = $ARGS{'Name'} .'-'
+ if $ARGS{'Name'}
+ && grep rindex($_, "$ARGS{'Name'}-Articles-", 0) == 0,
+ keys %$parent_args;
+
+foreach my $arg ( keys %$parent_args ) {
+ next if $name_prefix && substr($arg, 0, length($name_prefix)) ne $name_prefix;
+
+ my $Ticket = $ARGS{Ticket};
+ if ( !$Ticket and $parent_args->{id} and $parent_args->{id} ne 'new' ) {
+ $Ticket = RT::Ticket->new($session{'CurrentUser'});
+ $Ticket->Load($parent_args->{id});
+ unless ( $Ticket->id ) {
+ $RT::Logger->error("Couldn't load ticket ". $parent_args->{id} )
+ }
+ }
+
+ my $Queue = RT::Queue->new($session{CurrentUser});
+ if ($Ticket && $Ticket->Id) {
+ $Queue = $Ticket->QueueObj;
+ }
+
+ my $article = RT::Article->new($session{'CurrentUser'});
+ $article->LoadByInclude(
+ Field => substr($arg, length($name_prefix)),
+ Value => $parent_args->{$arg},
+ Queue => $Queue->Id,
+ );
+ next unless $article && $article->id;
+
+ my $formatted_article = $m->scomp('/Articles/Article/Elements/Preformatted',
+ Article => $article, Ticket => $Ticket
+ );
+
+ $m->callback( Article => $article, Ticket => $Ticket, formatted_article => \$formatted_article );
+
+ if (RT->Config->Get('MessageBoxRichText', $session{'CurrentUser'})) {
+ $formatted_article =~ s/>/&gt;/g;
+ $formatted_article =~ s/</&lt;/g;
+ $formatted_article =~ s/&/&amp;/g;
+ $formatted_article =~ s/\n/\n<br \/>/g;
+ }
+ $m->print($formatted_article);
+
+}
+return;
+</%INIT>
diff --git a/rt/share/html/Articles/Elements/NewestArticles b/rt/share/html/Articles/Elements/NewestArticles
new file mode 100644
index 000000000..444b2d89d
--- /dev/null
+++ b/rt/share/html/Articles/Elements/NewestArticles
@@ -0,0 +1,80 @@
+%# 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/TitleBoxStart, title => loc("[_1] newest articles", $rows), bodyclass=> '' &>
+<table border="0" cellspacing="0" cellpadding="1" width="100%">
+<tr>
+<th align="right"><&|/l&>#</&></th>
+<th align="left"><&|/l&>Name</&></th>
+<th align="left" width="20%"><&|/l&>Created by</&></th>
+<th align="left">&nbsp;</th>
+</tr>
+% while (my $Article = $MyArticles->Next) {
+% $i++;
+<tr class="<% $i%2 ? 'oddline' : 'evenline'%>">
+<td align="right"><%$Article->Id%></td>
+<td><a href="<% RT->Config->Get('WebPath') %>/Articles/Article/Display.html?id=<%$Article->Id%>"><%$Article->Name || loc('(no name)')%></a></td>
+<td><%$Article->CreatorObj->Name%></td>
+<td align="right">[<a href="<% RT->Config->Get('WebPath') %>/Articles/Article/Edit.html?id=<%$Article->Id%>"><&|/l&>Update</&></a>]</td>
+</tr>
+<tr class="<% $i%2 ? 'oddline' : 'evenline'%>">
+<td>&nbsp;</td>
+<td colspan="3"><small><%$Article->Summary || loc('(no Summary)')%></small></td>
+</tr>
+% }
+</table>
+<& /Elements/TitleBoxEnd &>
+<%INIT>
+my $rows = 10;
+my $i;
+my $MyArticles;
+$MyArticles = RT::Articles->new($session{'CurrentUser'});
+$MyArticles->UnLimit;
+$MyArticles->RowsPerPage($rows);
+$MyArticles->OrderBy(FIELD => 'LastUpdated', ORDER => 'DESC');
+
+</%INIT>
diff --git a/rt/share/html/Articles/Elements/QuickSearch b/rt/share/html/Articles/Elements/QuickSearch
new file mode 100644
index 000000000..f0c0d1c89
--- /dev/null
+++ b/rt/share/html/Articles/Elements/QuickSearch
@@ -0,0 +1,59 @@
+%# 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/TitleBoxStart, title => loc('Quick search') &>
+<ul>
+% while (my $class = $classes->Next) {
+<li><a href="<%RT->Config->Get('WebPath')%>/Articles/Article/Search.html?Class=<%$class->Name%>&Parent=0&HideOptions=1"><%$class->Name%></a></li>
+% }
+</ul>
+<& /Elements/TitleBoxEnd &>
+<%init>
+my $classes = RT::Classes->new($session{'CurrentUser'});
+$classes->LimitToEnabled;
+</%init>
+
diff --git a/rt/share/html/Articles/Elements/SelectClass b/rt/share/html/Articles/Elements/SelectClass
new file mode 100644
index 000000000..0ce90609e
--- /dev/null
+++ b/rt/share/html/Articles/Elements/SelectClass
@@ -0,0 +1,95 @@
+%# 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 }}}
+% if ($Lite) {
+<input name="<%$Name%>" size="25" default="<%$d->Name%>" />
+% } else {
+<select NAME ="<%$Name%>"
+% if ($Multiple) {
+MULTIPLE
+% }
+% if ($Size) {
+SIZE=<%$Size%>
+% }
+>
+% if ($ShowNullOption) {
+<option value="">-</option>
+% }
+% while (my $Class=$Classes->Next) {
+% next unless ($Class->Name); # if they can't see it, don't list it
+% if ($ShowAllClasses || $Class->CurrentUserHasRight('CreateArticle')) {
+<option VALUE="<%$Class->Id%>" <%(grep { $_ && ( ( /^\d+$/ && $Class->Id == $_ ) || $Class->Name eq $_ )} @Default) ? 'SELECTED' : '' %>><%$Class->Name%>
+% if (($Verbose) and ($Class->Description) ){
+(<%$Class->Description%>)
+% }
+</option>
+% }
+% }
+</select>
+% }
+<%ARGS>
+$Multiple => undef
+$Size => undef
+$ShowNullOption => 1
+$ShowAllClasses => 1
+$Name => undef
+$Verbose => undef
+$Default => undef
+$Lite => 0
+</%ARGS>
+
+<%INIT>
+
+my @Default = ref($Default) eq 'ARRAY' ? @$Default : ( $Default);
+
+my $Classes= RT::Classes->new($session{'CurrentUser'});
+$Classes->LimitToEnabled();
+
+my $d = RT::Class->new($session{'CurrentUser'});
+$d->Load($Default[0]);
+
+</%INIT>
diff --git a/rt/share/html/Articles/Elements/ShowTopic b/rt/share/html/Articles/Elements/ShowTopic
new file mode 100644
index 000000000..da7c5f213
--- /dev/null
+++ b/rt/share/html/Articles/Elements/ShowTopic
@@ -0,0 +1,64 @@
+%# 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 }}}
+% for (@path) {
+%# this isn't always a class, it can be the system object
+% my $class_id = ($_->ObjectType eq 'RT::Class' ? $_->ObjectId : 0 );
+<% $_->ParentObj->Id ? " > " : "" %><a href="<% RT->Config->Get('WebPath') %>/Articles/Topics.html?class=<% $class_id %>&id=<% $_->Id %>"><% $_->Name || loc("(no name)") %></a>
+% }
+
+<%args>
+$topic
+</%args>
+
+<%init>
+my @path;
+while ($topic->Id) {
+ unshift @path, $topic;
+ $topic = $topic->ParentObj;
+}
+</%init>
diff --git a/rt/share/html/Articles/Elements/UpdatedArticles b/rt/share/html/Articles/Elements/UpdatedArticles
new file mode 100644
index 000000000..f2c5226be
--- /dev/null
+++ b/rt/share/html/Articles/Elements/UpdatedArticles
@@ -0,0 +1,81 @@
+%# 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/TitleBoxStart, title => loc("[_1] most recently updated articles", $rows), bodyclass=> '' &>
+<table border="0" cellspacing="0" cellpadding="1" width="100%">
+<tr>
+<th align="right"><&|/l&>#</&></th>
+<th align="left"><&|/l&>Name</&></th>
+<th align="left" width="20%"><&|/l&>Created by</&></th>
+<th>&nbsp;</th>
+</tr>
+
+% while (my $Article = $MyArticles->Next) {
+% $i++;
+<tr class="<% $i%2 ? 'oddline' : 'evenline'%>">
+<td align="right"><%$Article->Id%></td>
+<td><a href="<% RT->Config->Get('WebPath') %>/Articles/Article/Display.html?id=<%$Article->Id%>"><%$Article->Name || loc('(no name)')%></a></td>
+<td><%$Article->CreatorObj->Name%></td>
+<td align="right">[<a href="<% RT->Config->Get('WebPath') %>/Articles/Article/Edit.html?id=<%$Article->Id%>"><&|/l&>Update</&></a>]</td>
+</tr>
+<tr class="<% $i%2 ? 'oddline' : 'evenline'%>">
+<td>&nbsp;</td>
+<td colspan="3"><small><%$Article->Summary || loc('(no Summary)')%></small></td>
+</tr>
+% }
+</table>
+<& /Elements/TitleBoxEnd &>
+<%INIT>
+my $rows = 10;
+my $i;
+my $MyArticles;
+$MyArticles = RT::Articles->new($session{'CurrentUser'});
+$MyArticles->RowsPerPage($rows);
+$MyArticles->Limit(FIELD => 'Created', OPERATOR => '!=', VALUE => 'LastUpdated', QUOTEVALUE => 0 );
+$MyArticles->OrderBy(FIELD => 'Created', ORDER => 'DESC');
+
+</%INIT>
diff --git a/rt/share/html/Articles/Topics.html b/rt/share/html/Articles/Topics.html
new file mode 100644
index 000000000..9a07c089a
--- /dev/null
+++ b/rt/share/html/Articles/Topics.html
@@ -0,0 +1,276 @@
+%# 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 &>
+<a href="Topics.html"><&|/l&>All topics</&></a>
+% if (defined $class) {
+&gt; <a href="Topics.html?class=<%$currclass_id%>"><% $currclass_name %></a>
+% }
+
+% if ($id != 0) {
+&gt; <& /Articles/Elements/ShowTopic, topic => $currtopic &>
+% }
+<br />
+<h1><&|/l&>Browse by topic</&></h1>
+<%perl>
+if (defined $class) {
+ $m->print('<h2>'.'<a href="'.
+ RT->Config->Get('WebPath')."/Articles/Topics.html?class=" . $currclass_id
+ .'">'.$currclass_name."</a></h2>\n");
+ ProduceTree(\@Actions, $currclass, $currclass_id, $currclass_name, 0, $id);
+} else {
+ $m->print("<ul>\n");
+ while (my $c = $Classes->Next) {
+ $m->print('<li><h2>'.'<a href="'.
+ RT->Config->Get('WebPath')."/Articles/Topics.html?class=" . $c->Id
+ .'">'.$c->Name."</a></h2>\n");
+ $m->print("\n</li>\n");
+ }
+ $m->print(qq|<li><h2><a href="|.RT->Config->Get('WebPath').qq|/Articles/Topics.html?class=0">|.loc('Global Topics').qq|</a></h2></li>\n|);
+ $m->print("</ul>\n");
+}
+</%perl>
+
+<br />
+<%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};
+}
+</%perl>
+
+% if (@articles) {
+% if ($id) {
+<h2><&|/l, $currtopic->Name&>Articles in [_1]</&></h2>
+% } elsif ($class) {
+<h2><&|/l&>Articles with no topics</&></h2>
+% }
+<ul>
+% for my $a (@articles) {
+<li><a href="Article/Display.html?id=<% $a->Id %>"><% $a->Name || loc("(no name)") %></a></li>
+% }
+</ul>
+% }
+
+<%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 "<ul>";
+ 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 "</ul>" 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 "<ul>" 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 "</ul>\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(<li><a href="$query">$topic_info</a>);
+ } else {
+ $output = qq(<li>$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(<a href="$query">$article_text</a>);
+ }
+
+ $output .= "</li>\n";
+
+ } else {
+
+ # This builds a link for the class specified, with no particular topic.
+ $query = "Topics.html?class=" . $currclass_id;
+ $output = "<li><a href=\"$query\">" . $currclass_name . "</a>";
+ $output .= ": " . $currclass->Description if $currclass->Description;
+ }
+
+ return $output;
+}
+
+</%init>
+
+<%args>
+$id => 0
+$class => undef
+$showall => undef
+</%args>
diff --git a/rt/share/html/Articles/index.html b/rt/share/html/Articles/index.html
new file mode 100644
index 000000000..c4a1eab4e
--- /dev/null
+++ b/rt/share/html/Articles/index.html
@@ -0,0 +1,63 @@
+%# 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('Articles') &>
+<& /Elements/Tabs &>
+<table width="100%">
+<tr>
+<td valign="top" width="70%">
+<& /Articles/Elements/NewestArticles &>
+<br />
+<& /Articles/Elements/UpdatedArticles &>
+</td>
+<td valign="top">
+<& /Articles/Elements/QuickSearch &>
+<br />
+<& /Articles/Elements/CreateArticle &>
+</td>
+</tr>
+</table>