diff options
Diffstat (limited to 'rt/html/Search/Build.html')
-rw-r--r-- | rt/html/Search/Build.html | 832 |
1 files changed, 0 insertions, 832 deletions
diff --git a/rt/html/Search/Build.html b/rt/html/Search/Build.html deleted file mode 100644 index fa84f42a7..000000000 --- a/rt/html/Search/Build.html +++ /dev/null @@ -1,832 +0,0 @@ -%# BEGIN BPS TAGGED BLOCK {{{ -%# -%# COPYRIGHT: -%# -%# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC -%# <jesse@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 }}} -%# -%# Data flow here: -%# The page receives a Query from the previous page, and maybe arguments -%# corresponding to actions. (If it doesn't get a Query argument, it pulls -%# one out of the session hash. Also, it could be getting just a raw query from -%# Build/Edit.html (Advanced).) -%# -%# After doing some stuff with default arguments and saved searches, the ParseQuery -%# function (which is similar to, but not the same as, _parser in RT/Tickets_Overlay_SQL) -%# converts the Query into a RT::Interface::Web::QueryBuilder::Tree. This mason file -%# then adds stuff to or modifies the tree based on the actions that had been requested -%# by clicking buttons. It then calls GetQueryAndOptionList on the tree to generate -%# the SQL query (which is saved as a hidden input) and the option list for the Clauses -%# box in the top right corner. -%# -%# Worthwhile refactoring: the tree manipulation code for the actions could use some cleaning -%# up. The node-adding code is different in the "add" actions from in ParseQuery, which leads -%# to things like ParseQuery correctly not quoting numbers in numerical fields, while the "add" -%# action does quote it (this breaks SQLite). -%# -<& /Elements/Header, Title => $title &> -<& /Ticket/Elements/Tabs, - current_tab => "Search/Build.html".$QueryString, - Title => $title, - Format => $Format, - Query => $Query, - Order => $Order, - OrderBy => $OrderBy, - Rows => $RowsPerPage -&> - -<form method="post" action="Build.html" name="BuildQuery"> -<input type="hidden" class="hidden" name="SearchId" value="<%$SearchId%>" /> -<input type="hidden" class="hidden" name="Query" value="<%$Query%>" /> -<input type="hidden" class="hidden" name="Format" value="<%$Format%>" /> -<table width="100%" border="0" cellpadding="5"> -<tr valign="top"> -<td class="boxcontainer" rowspan="2" width="65%"> -<& Elements/PickCriteria, query => $Query, cfqueues => $queues &> -<& /Elements/Submit, Caption => loc('Add these terms to your search'), Label => loc('Add'), Name => 'AddClause'&> -</td> - -<td> -<& Elements/EditQuery, - %ARGS, - actions => \@actions, - optionlist => $optionlist, - Description => $Description &> -<& /Elements/Submit, Label => loc('Add and Search'), Name => 'DoSearch'&> -</td> -</tr> - -<tr valign="top"> -<td> -<& Elements/EditSearches, CurrentSearch => $search_hash, Dirty => $dirty, SearchId => $SearchId &> -</td> -</tr> - -<tr> -<td colspan="2" class="boxcontainer"> - -<& Elements/DisplayOptions, %ARGS, Format=> $Format, -AvailableColumns => $AvailableColumns, CurrentFormat => $CurrentFormat, RowsPerPage => $RowsPerPage, OrderBy => $OrderBy, Order => $Order &> -<& /Elements/Submit, Label => loc('Add and Search'), Name => 'DoSearch'&> -</td> -</tr> -</table> -</form> - -<%INIT> -use RT::Interface::Web::QueryBuilder; -use RT::Interface::Web::QueryBuilder::Tree; - -my $search_hash = {}; -my $search; -my $title = loc("Query Builder"); - -# {{{ Clear out unwanted data -if ( $NewQuery or $ARGS{'Delete'} ) { - - # Wipe all data-carrying variables clear if we want a new - # search, or we're deleting an old one.. - $Query = ''; - $Format = ''; - $Description = ''; - $SearchId = ''; - $Order = ''; - $OrderBy = ''; - $RowsPerPage = undef; - - # ($search hasn't been set yet; no need to clear) - - # ..then wipe the session out.. - undef $session{'CurrentSearchHash'}; - - # ..and the search results. - $session{'tickets'}->CleanSlate() if defined $session{'tickets'}; -} - -# }}} - -if (ref $OrderBy eq "ARRAY") { - $OrderBy = join("|", @$OrderBy); -} -if (ref $Order eq "ARRAY") { - $Order = join("|", @$Order); -} - -# {{{ Attempt to load what we can from the session, set defaults - -# We don't read or write to the session again until the end -$search_hash = $session{'CurrentSearchHash'}; - -# Read from user preferences -my $prefs = $session{'CurrentUser'}->UserObj->Preferences("SearchDisplay") || {}; - -# These variables are what define a search_hash; this is also -# where we give sane defaults. -$Query ||= $search_hash->{'Query'}; -$Format ||= $search_hash->{'Format'} || $prefs->{'Format'}; -$Description ||= $search_hash->{'Description'}; -$SearchId ||= $search_hash->{'SearchId'} || 'new'; -$Order ||= $search_hash->{'Order'} || $prefs->{'Order'} || 'ASC'; -$OrderBy ||= $search_hash->{'OrderBy'} || $prefs->{'OrderBy'} || 'id'; - -unless ( defined $RowsPerPage ) { - if ( defined $search_hash->{'RowsPerPage'} ) { - $RowsPerPage = $search_hash->{'RowsPerPage'}; - } - elsif ( defined $prefs->{'RowsPerPage'} ) { - $RowsPerPage = $prefs->{'RowsPerPage'}; - } - else { - $RowsPerPage = 50; - } -} - - $search ||= $search_hash->{'Object'}; - -# }}} - -my @actions = (); - -# Clean unwanted junk from the format -$Format = $m->comp( '/Elements/ScrubHTML', Content => $Format ) if ($Format); - -# {{{ If we're asked to delete the current search, make it go away and reset the search parameters -if ( $ARGS{'Delete'} ) { - - # We set $SearchId to 'new' above already, so peek into the %ARGS - my ($container_object, $search_id) = _parse_saved_search ($ARGS{'SearchId'}); - if ($container_object && $container_object->id) { - # We have the object the entry is an attribute on; delete the - # entry.. - $container_object->Attributes->DeleteEntry( - Name => 'SavedSearch', - id => $search_id - ); - } -} - -# }}} - -# {{{ If the user wants to copy a search, uncouple from the one that this was based on, but don't erase the $Query or $Format -if ( $ARGS{'CopySearch'} ) { - $SearchId = 'new'; - $search = undef; - $Description = loc( "[_1] copy", $Description ); -} - -# }}} - -# {{{ if we're asked to revert the current search, we just want to load it -if ( $ARGS{'Revert'} ) { - $ARGS{'LoadSavedSearch'} = $SearchId; -} - -# }}} - -# {{{ if we're asked to load a search, load it. - -if ( my ($container_object, $search_id ) = _parse_saved_search ($ARGS{'LoadSavedSearch'})) { - $search = $container_object->Attributes->WithId($search_id); - - # We have a $search and now; import the others - $SearchId = $ARGS{'LoadSavedSearch'}; - $Description = $search->Description; - $Format = $search->SubValue('Format'); - $Query = $search->SubValue('Query'); - $Order = $search->SubValue('Order'); - $OrderBy = $search->SubValue('OrderBy'); - $RowsPerPage = $search->SubValue('RowsPerPage'); -} - -# }}} - -# {{{ if we're asked to save the current search, save it -if ( $ARGS{'Save'} ) { - if ( $search && $search->id ) { - # permission check - if ($search->Object->isa('RT::System')) { - unless ($session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'SuperUser')) { - Abort("No permission to save system-wide searches"); - } - } - - # This search is based on a previously loaded search -- so - # just update the current search object with new values - $search->SetSubValues( - Format => $Format, - Query => $Query, - Order => $Order, - OrderBy => $OrderBy, - RowsPerPage => $RowsPerPage, - ); - $search->SetDescription($Description); - - } - elsif ( $SearchId eq 'new' ) { - my $saved_search = RT::SavedSearch->new( $session{'CurrentUser'} ); - my ( $ok, $search_msg ) = $saved_search->Save( - Privacy => $ARGS{'Owner'}, - Name => $Description, - SearchParams => { - Format => $Format, - Query => $Query, - Order => $Order, - OrderBy => $OrderBy, - RowsPerPage => $RowsPerPage } ); - - if ($ok) { - $search = $session{'CurrentUser'}->UserObj->Attributes->WithId($saved_search->Id); - # Build new SearchId - $SearchId = - ref( $session{'CurrentUser'}->UserObj ) . '-' - . $session{'CurrentUser'}->UserObj->Id - . '-SavedSearch-' - . $search->Id; - } - else { - push @actions, [ loc("Can't find a saved search to work with").': '.loc($search_msg), 0 ]; - } - } - else { - push @actions, [ loc("Can't save this search"), 0 ]; - } - -} - -# }}} - - -# {{{ Parse the query -use Regexp::Common qw /delimited/; - -# States -use constant VALUE => 1; -use constant AGGREG => 2; -use constant OP => 4; -use constant PAREN => 8; -use constant KEYWORD => 16; - -my $_match = sub { - - # Case insensitive equality - my ( $y, $x ) = @_; - return 1 if $x =~ /^$y$/i; - - # return 1 if ((lc $x) eq (lc $y)); # Why isnt this equiv? - return 0; -}; - -my $ParseQuery = sub { - my $string = shift; - my $tree = shift; - my $actions = shift; - my $want = KEYWORD | PAREN; - my $last = undef; - - my $depth = 1; - - # make a tree root - $$tree = RT::Interface::Web::QueryBuilder::Tree->new; - my $root = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $$tree ); - my $parentnode = $root; - - # on new searches, we're passed undef but still need to construct the - # RT::Interface::Web::QueryBuilder::Tree. Quiet warning - return unless defined $string; - - # get the FIELDS from Tickets_Overlay - my $tickets = new RT::Tickets( $session{'CurrentUser'} ); - my %FIELDS = %{ $tickets->FIELDS }; - - # Lower Case version of FIELDS, for case insensitivity - my %lcfields = map { ( lc($_) => $_ ) } ( keys %FIELDS ); - - my @tokens = qw[VALUE AGGREG OP PAREN KEYWORD]; - my $re_aggreg = qr[(?i:AND|OR)]; - my $re_value = qr[$RE{delimited}{-delim=>qq{\'\"}}|\d+]; - my $re_keyword = qr[$RE{delimited}{-delim=>qq{\'\"}}|(?:\{|\}|\w|\.)+]; - my $re_op = - qr[=|!=|>=|<=|>|<|(?i:IS NOT)|(?i:IS)|(?i:NOT LIKE)|(?i:LIKE)] - ; # long to short - my $re_paren = qr'\(|\)'; - - # assume that $ea is AND if it is not set - my ( $ea, $key, $op, $value ) = ( "AND", "", "", "" ); - - # order of matches in the RE is important.. op should come early, - # because it has spaces in it. otherwise "NOT LIKE" might be parsed - # as a keyword or value. - - while ( - $string =~ /( - $re_aggreg - |$re_op - |$re_keyword - |$re_value - |$re_paren - )/igx - ) - { - my $val = $1; - my $current = 0; - - # Highest priority is last - $current = OP if $_match->( $re_op, $val ); - $current = VALUE if $_match->( $re_value, $val ); - $current = KEYWORD - if $_match->( $re_keyword, $val ) && ( $want & KEYWORD ); - $current = AGGREG if $_match->( $re_aggreg, $val ); - $current = PAREN if $_match->( $re_paren, $val ); - - unless ( $current && $want & $current ) { - - # Error - # FIXME: I will only print out the highest $want value - my $token = $tokens[ ( ( log $want ) / ( log 2 ) ) ]; - push @$actions, - [ - loc("Error near ->[_1]<- expecting a [_2] in '[_3]'", - $val, $token, $string ), - -1 - ]; - } - - # State Machine: - my $parentdepth = $depth; - - # Parens are highest priority - if ( $current & PAREN ) { - if ( $val eq "(" ) { - $depth++; - - # make a new node that the clauses can be children of - $parentnode = RT::Interface::Web::QueryBuilder::Tree->new( $ea, $parentnode ); - } - else { - $depth--; - $parentnode = $parentnode->getParent(); - } - - $want = KEYWORD | PAREN | AGGREG; - } - elsif ( $current & AGGREG ) { - $ea = $val; - $parentnode->setNodeValue($ea); - $want = KEYWORD | PAREN; - } - elsif ( $current & KEYWORD ) { - $key = $val; - $want = OP; - } - elsif ( $current & OP ) { - $op = $val; - $want = VALUE; - } - elsif ( $current & VALUE ) { - $value = $val; - - # Remove surrounding quotes from $key, $val - # (in future, simplify as for($key,$val) { action on $_ }) - if ( $key =~ /$RE{delimited}{-delim=>qq{\'\"}}/ ) { - substr( $key, 0, 1 ) = ""; - substr( $key, -1, 1 ) = ""; - } - if ( $val =~ /$RE{delimited}{-delim=>qq{\'\"}}/ ) { - substr( $val, 0, 1 ) = ""; - substr( $val, -1, 1 ) = ""; - } - - # Unescape escaped characters - $key =~ s!\\(.)!$1!g; - $val =~ s!\\(.)!$1!g; - - my $class; - - my ($key_base, $subkey) = split(/\./,$key,2); - $key_base =~ s/\..*$//; # Strip off .EmailAddress, for example - - if ( exists $lcfields{lc $key_base } ) { - $key = $lcfields{lc $key_base } . (defined $subkey ? '.'.$subkey : ''); - $class = $FIELDS{$key_base}->[0]; - } - elsif ( $key =~ /^C(?:ustom)?F(?:ield)?\.{(.*)}$/i ) { - $class = $FIELDS{'CF'}->[0]; - } - - if ( $class ne 'INT' ) { - $val = "'$val'"; - } - - push @$actions, [ loc("Unknown field: [_1]", $key), -1 ] unless $class; - - $want = PAREN | AGGREG; - } - else { - push @$actions, [ loc("I'm lost"), -1 ]; - } - - if ( $current & VALUE ) { - if ( $key =~ /^CF./ ) { - $key = "'" . $key . "'"; - } - my $clause = { - Key => $key, - Op => $op, - Value => $val - }; - - # explicity add a child to it - RT::Interface::Web::QueryBuilder::Tree->new( $clause, $parentnode ); - - ( $ea, $key, $op, $value ) = ( "", "", "", "" ); - - } - - $last = $current; - } # while - - push @$actions, [ loc("Incomplete query"), -1 ] - unless ( ( $want | PAREN ) || ( $want | KEYWORD ) ); - - push @$actions, [ loc("Incomplete Query"), -1 ] - unless ( $last && ( $last | PAREN ) || ( $last || VALUE ) ); - - # This will never happen, because the parser will complain - push @$actions, [ loc("Mismatched parentheses"), -1 ] - unless $depth == 1; -}; - -my $tree; -{ - my @parsing_errors; - $ParseQuery->( $Query, \$tree, \@parsing_errors ); - - # if parsing went poorly, send them to the edit page - # to fix it - if ( @parsing_errors ) { - return $m->comp( - "Edit.html", - Query => $Query, - actions => \@parsing_errors - ); - } -} - -$Query = ""; - -my @options = $tree->GetDisplayedNodes; - -my @current_values = grep { defined } @options[@clauses]; - -# {{{ Move things around -if ( $ARGS{"Up"} ) { - if (@current_values) { - foreach my $value (@current_values) { - my $index = $value->getIndex(); - if ( $value->getIndex() > 0 ) { - my $parent = $value->getParent(); - $parent->removeChild($index); - $parent->insertChild( $index - 1, $value ); - $value = $parent->getChild( $index - 1 ); - } - else { - push( @actions, [ loc("error: can't move up"), -1 ] ); - } - } - } - else { - push( @actions, [ loc("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"Down"} ) { - if (@current_values) { - foreach my $value (@current_values) { - my $index = $value->getIndex(); - my $parent = $value->getParent(); - if ( $value->getIndex() < ( $parent->getChildCount - 1 ) ) { - $parent->removeChild($index); - $parent->insertChild( $index + 1, $value ); - $value = $parent->getChild( $index + 1 ); - } - else { - push( @actions, [ loc("error: can't move down"), -1 ] ); - } - } - } - else { - push( @actions, [ loc("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"Left"} ) { - if (@current_values) { - foreach my $value (@current_values) { - my $parent = $value->getParent(); - my $grandparent = $parent->getParent(); - if ( !$grandparent->isRoot ) { - my $index = $parent->getIndex(); - $parent->removeChild($value); - $grandparent->insertChild( $index, $value ); - if ( $parent->isLeaf() ) { - $grandparent->removeChild($parent); - } - } - else { - push( @actions, [ loc("error: can't move left"), -1 ] ); - } - } - } - else { - push( @actions, [ loc("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"Right"} ) { - if (@current_values) { - foreach my $value (@current_values) { - my $parent = $value->getParent(); - my $index = $value->getIndex(); - my $newparent; - if ( $index > 0 ) { - my $sibling = $parent->getChild( $index - 1 ); - if ( ref( $sibling->getNodeValue ) ) { - $parent->removeChild($value); - my $newtree = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $parent ); - $newtree->addChild($value); - } - else { - $parent->removeChild($index); - $sibling->addChild($value); - } - } - else { - $parent->removeChild($value); - $newparent = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $parent ); - $newparent->addChild($value); - } - } - } - else { - push( @actions, [ loc("error: nothing to move"), -1 ] ); - } -} -elsif ( $ARGS{"DeleteClause"} ) { - if (@current_values) { - $_->getParent()->removeChild($_) for @current_values; - @current_values = (); - } - else { - push( @actions, [ loc("error: nothing to delete"), -1 ] ); - } -} -elsif ( $ARGS{"Toggle"} ) { - my $ea; - if (@current_values) { - foreach my $value (@current_values) { - my $parent = $value->getParent(); - - if ( $parent->getNodeValue eq 'AND' ) { - $parent->setNodeValue('OR'); - } - else { - $parent->setNodeValue('AND'); - } - } - } - else { - push( @actions, [ loc("error: nothing to toggle"), -1 ] ); - } -} - -# {{{ Try to find if we're adding a clause -foreach my $arg ( keys %ARGS ) { - if ( - $arg =~ m/^ValueOf(\w+|'CF.{.*?}')$/ - && ( ref $ARGS{$arg} eq "ARRAY" - ? grep { $_ ne "" } @{ $ARGS{$arg} } - : $ARGS{$arg} ne "" ) - ) - { - - # We're adding a $1 clause - my $field = $1; - my ( $keyword, $op, $value ); - - #figure out if it's a grouping - if ( $ARGS{ $field . "Field" } ) { - $keyword = $ARGS{ $field . "Field" }; - } - else { - $keyword = $field; - } - - my ( @ops, @values ); - if ( ref $ARGS{ 'ValueOf' . $field } eq "ARRAY" ) { - - # we have many keys/values to iterate over, because there is - # more than one CF with the same name. - @ops = @{ $ARGS{ $field . 'Op' } }; - @values = @{ $ARGS{ 'ValueOf' . $field } }; - } - else { - @ops = ( $ARGS{ $field . 'Op' } ); - @values = ( $ARGS{ 'ValueOf' . $field } ); - } - $RT::Logger->error("Bad Parameters passed into Query Builder") - unless @ops == @values; - - for my $i ( 0 .. @ops - 1 ) { - my ( $op, $value ) = ( $ops[$i], $values[$i] ); - next if $value eq ""; - - if ( $value eq 'NULL' && $op =~ /=/ ) { - if ( $op eq '=' ) { - $op = "IS"; - } - elsif ( $op eq '!=' ) { - $op = "IS NOT"; - } - - # This isn't "right", but... - # It has to be this way until #5182 is fixed - $value = "'NULL'"; - } - else { - $value = "'$value'"; - } - - my $clause = { - Key => $keyword, - Op => $op, - Value => $value - }; - - my $newnode = RT::Interface::Web::QueryBuilder::Tree->new($clause); - if (@current_values) { - foreach my $value (@current_values) { - my $newindex = $value->getIndex() + 1; - $value->insertSibling( $newindex, $newnode ); - $value = $newnode; - } - } - else { - $tree->getChild(0)->addChild($newnode); - @current_values = $newnode; - } - $newnode->getParent()->setNodeValue( $ARGS{'AndOr'} ); - } - } -} - -# }}} - -$tree->PruneChildlessAggregators; - -# }}} - -# {{{ Rebuild $Query based on the additions / movements -$Query = ""; -my $optionlist_arrayref; - -($Query, $optionlist_arrayref) = $tree->GetQueryAndOptionList(\@current_values); - -my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) - . (" " x (5 * $_->{DEPTH})) - . $m->interp->apply_escapes($_->{TEXT}, 'h') . qq(</option>) } @$optionlist_arrayref; - - - - -# }}} - -# }}} - -my $queues = $tree->GetReferencedQueues; - -# {{{ Deal with format changes -my ( $AvailableColumns, $CurrentFormat ); -( $Format, $AvailableColumns, $CurrentFormat ) = $m->comp( - 'Elements/BuildFormatString', - cfqueues => $queues, - %ARGS, Format => $Format -); - -# }}} - -# {{{ If we're modifying an old query, check if it has changed -my $dirty = 0; -$dirty = 1 - if defined $search - and ($search->SubValue('Format') ne $Format - or $search->SubValue('Query') ne $Query - or $search->SubValue('Order') ne $Order - or $search->SubValue('OrderBy') ne $OrderBy - or $search->SubValue('RowsPerPage') ne $RowsPerPage ); - -# }}} - -# {{{ Push the updates into the session so we don't loose 'em -$search_hash->{'SearchId'} = $SearchId; -$search_hash->{'Format'} = $Format; -$search_hash->{'Query'} = $Query; -$search_hash->{'Description'} = $Description; -$search_hash->{'Object'} = $search; -$search_hash->{'Order'} = $Order; -$search_hash->{'OrderBy'} = $OrderBy; -$search_hash->{'RowsPerPage'} = $RowsPerPage; - -$session{'CurrentSearchHash'} = $search_hash; - -# }}} - -# {{{ Show the results, if we were asked. -if ( $ARGS{"DoSearch"}) { - $m->comp( - "Results.html", - Query => $Query, - Format => $Format, - Order => $Order, - OrderBy => $OrderBy, - Rows => $RowsPerPage - ); - $m->comp('/Elements/Footer'); - $m->abort(); -} - -# }}} - -# {{{ Build a querystring for the tabs - -my $QueryString; -if ($NewQuery) { - $QueryString = '?NewQuery=1'; -} -else { - $QueryString = '?' - . $m->comp( - '/Elements/QueryString', - Query => $Query, - Format => $Format, - Order => $Order, - OrderBy => $OrderBy, - Rows => $RowsPerPage - ) - if ($Query); -} - -# }}} - -</%INIT> - -<%ARGS> -$NewQuery => 0 -$SearchId => undef -$Query => undef -$Format => undef -$Description => undef -$Order => undef -$OrderBy => undef -$RowsPerPage => undef -$HideResults => 0 -@clauses => () -</%ARGS> - |