[Rt-commit] r3107 - in rt/branches/QUEBEC-EXPERIMENTAL: .
html/Admin/Queues html/Elements html/Search lib/RT
lib/RT/Action lib/RT/I18N lib/RT/Interface/Web
lib/RT/Interface/Web/QueryBuilder lib/t/regression sbin
jesse at bestpractical.com
jesse at bestpractical.com
Wed Jun 8 23:06:21 EDT 2005
Author: jesse
Date: Wed Jun 8 23:06:16 2005
New Revision: 3107
Added:
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder/
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder.pm (contents, props changed)
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder/Tree.pm (contents, props changed)
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/21query-builder.t
Modified:
rt/branches/QUEBEC-EXPERIMENTAL/ (props changed)
rt/branches/QUEBEC-EXPERIMENTAL/html/Admin/Queues/Modify.html
rt/branches/QUEBEC-EXPERIMENTAL/html/Elements/Error
rt/branches/QUEBEC-EXPERIMENTAL/html/Search/Build.html
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Action/AutoOpen.pm
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/cs.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/da.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/de.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/es.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fi.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fr.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/he.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/hu.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/it.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ja.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/nl.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/no.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pl.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pt_br.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ru.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_cn.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_tw.po
rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/02basic_web.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/04send_email.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/09record_cf_api.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/10merge.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/11-template-insert.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/12-search.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/13-attribute-tests.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/15cf_single_values_are_single.t
rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/20savedsearch.t
rt/branches/QUEBEC-EXPERIMENTAL/sbin/rt-test-dependencies.in
Log:
r19664 at hualien: jesse | 2005-06-08 18:41:46 -0400
r19152 at hualien: jesse | 2005-06-02 01:36:59 -0400
r18763 at hualien (orig r2992): kevinr | 2005-05-31 16:10:01 -0400
r2965 at sad-girl-in-snow: kevinr | 2005-05-25 17:47:26 -0400
* changed "e-mail" back to "email"
* removed discussion of pre-5.8.3 perl versions
r18764 at hualien (orig r2993): kevinr | 2005-05-31 16:10:33 -0400
r2967 at sad-girl-in-snow: kevinr | 2005-05-25 18:37:20 -0400
* Added a comma where a compound sentence wanted it.
r18765 at hualien (orig r2994): kevinr | 2005-05-31 16:11:31 -0400
r3004 at sad-girl-in-snow: kevinr | 2005-05-31 15:52:19 -0400
RT-Ticket: 6684
RT-Status: resolve
RT-Action: correspond
html/Elements/Error should not continue, and has been changed to add the
standard footer element on %cleanup.
r18766 at hualien (orig r2995): kevinr | 2005-05-31 20:34:40 -0400
r3008 at SAD-GIRL-IN-SNOW: kevinr | 2005-05-31 17:05:08 -0400
RT-Ticket: 6423
RT-Status: resolve
RT-Action: correspond
* Corrected a typo in Admin/Queues/Modify.html and propagated it to all the
po files, as per Angelo Turetta's suggestion.
r18767 at hualien (orig r2996): kevinr | 2005-05-31 20:35:39 -0400
r3009 at SAD-GIRL-IN-SNOW: kevinr | 2005-05-31 17:52:48 -0400
RT-Ticket: 6669
RT-Status: resolved
RT-Action: correspond
* Fixed an extra space in lib/RT/Transaction_Overlay.pm and propagated the
change to the po files, as per Brandon Pulsipher's suggestion.
r18768 at hualien (orig r2997): kevinr | 2005-05-31 20:38:19 -0400
r3010 at SAD-GIRL-IN-SNOW: kevinr | 2005-05-31 18:10:17 -0400
RT-Ticket: 6423
RT-Status: resolve
RT-Action: correspond
* Fixed a line I broke in revision 3008 -- vi removed the '%1'.
r18769 at hualien (orig r2998): kevinr | 2005-05-31 21:08:40 -0400
r3841 at SAD-GIRL-IN-SNOW: kevinr | 2005-05-31 21:07:42 -0400
RT-Ticket: 6669
RT-Status: resolved
RT-Action: correspond
* Fixed the mysteriously-absent '1' in the Norwegian po.
r18826 at hualien (orig r3039): glasser | 2005-06-01 18:32:16 -0400
r33100 at tin-foil: glasser | 2005-05-25 20:21:43 -0400
Mini refactoring of Tree->SQL/HTML function
r18827 at hualien (orig r3040): glasser | 2005-06-01 18:32:34 -0400
r33101 at tin-foil: glasser | 2005-05-25 21:05:02 -0400
Attempt to add parentheses to the clauses select list, in Query Builder.
r18828 at hualien (orig r3041): glasser | 2005-06-01 18:33:51 -0400
r33102 at tin-foil: glasser | 2005-05-25 22:22:53 -0400
build_array was being called twice for two totally disconnected reasons. Split one out.
r18829 at hualien (orig r3042): glasser | 2005-06-01 18:34:38 -0400
r33103 at tin-foil: glasser | 2005-05-25 22:24:07 -0400
And remove the old functionality too.
r18830 at hualien (orig r3043): glasser | 2005-06-01 18:34:56 -0400
r33104 at tin-foil: glasser | 2005-05-25 23:53:28 -0400
Fix mistake in the function I just made
Add a bit of testing of the query builder.
r18831 at hualien (orig r3044): glasser | 2005-06-01 18:35:14 -0400
r33105 at tin-foil: glasser | 2005-05-26 00:02:36 -0400
Run 'make license-tag'
r18832 at hualien (orig r3045): glasser | 2005-06-01 18:35:33 -0400
r33106 at tin-foil: glasser | 2005-05-26 01:21:29 -0400
Move stuff out from html/Search/Build.html into a module; refactor some of the code there.
r18833 at hualien (orig r3046): glasser | 2005-06-01 18:35:53 -0400
r33107 at tin-foil: glasser | 2005-05-26 01:56:25 -0400
More Query Builder tree refactoring.
r18834 at hualien (orig r3047): glasser | 2005-06-01 18:36:24 -0400
r33108 at tin-foil: glasser | 2005-05-26 02:12:48 -0400
rt-ticket: 6568
rt-update: correspond
* Better fix to Query Builder; in addition to refactoring most of the code which got
information out of the tree, prune away childless AND/ORs, fixing the bug from ticket #6568.
Also get rid of the reaction to the "Clear" action, which I don't think exists, and which
I think is incorrect, since the root is supposed to have one child (see where it is
first created).
r18835 at hualien (orig r3048): glasser | 2005-06-01 18:36:40 -0400
r33109 at tin-foil: glasser | 2005-05-26 12:02:13 -0400
More docs and refactoring on QueryBuilder::Tree
r18836 at hualien (orig r3049): glasser | 2005-06-01 18:36:55 -0400
r33110 at tin-foil: glasser | 2005-05-26 13:33:06 -0400
Undo 'make license-tag' change; jesse should do this later though
r18837 at hualien (orig r3050): glasser | 2005-06-01 18:37:12 -0400
r18838 at hualien (orig r3051): glasser | 2005-06-01 18:37:29 -0400
r33242 at tin-foil: glasser | 2005-05-27 14:08:19 -0400
* Improved Query builder Tests
* add plans to a bunch of other tests
r18839 at hualien (orig r3052): glasser | 2005-06-01 18:37:45 -0400
r33243 at tin-foil: glasser | 2005-05-27 17:08:38 -0400
Add some hopefully correct comments to the head of Search/Build
r18840 at hualien (orig r3053): glasser | 2005-06-01 18:38:05 -0400
r33652 at tin-foil: glasser | 2005-06-01 15:02:58 -0400
A mini rewrite of testdeps: now it tells you at the bottom if it is missing anything
r18841 at hualien (orig r3054): glasser | 2005-06-01 18:38:38 -0400
r33653 at tin-foil: glasser | 2005-06-01 15:19:20 -0400
fixdeps wasn't working for me (it was trying to detar inside my MiniCPAN!);
its code was "correct" but presumably one of the other 500 modules that were
loaded confused CPAN. (This bug happened both before and after the previous change.)
Now just uses a system() call to install.
r18842 at hualien (orig r3055): glasser | 2005-06-01 18:39:12 -0400
r33654 at tin-foil: glasser | 2005-06-01 16:36:18 -0400
Fix some test plans, mark some QB tests TODO
r18843 at hualien (orig r3056): glasser | 2005-06-01 18:39:36 -0400
r18844 at hualien (orig r3057): robert | 2005-06-02 00:15:13 -0400
r3073 at bear: rspier | 2005-06-02T04:14:40.726890Z
Support for RT-Control: no-autoopen
Modified: rt/branches/QUEBEC-EXPERIMENTAL/html/Admin/Queues/Modify.html
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/html/Admin/Queues/Modify.html (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/html/Admin/Queues/Modify.html Wed Jun 8 23:06:16 2005
@@ -72,13 +72,13 @@
<&|/l&>Reply Address</&>:
</TD><TD>
<INPUT name="CorrespondAddress" value="<% ($Create) ? "" : $QueueObj->CorrespondAddress %>">
-<BR><font size="-1"><i><&|/l , $RT::CorrespondAddress&>(If left blank, will default to [_1]</&></i></font>
+<BR><font size="-1"><i><&|/l , $RT::CorrespondAddress&>(If left blank, will default to [_1])</&></i></font>
</TD>
<TD ALIGN=RIGHT>
<&|/l&>Comment Address</&>: </TD><TD>
<INPUT NAME="CommentAddress" value="<% ($Create) ? "" : $QueueObj->CommentAddress %>">
-<BR><font size="-1"><i><&|/l , $RT::CommentAddress&>(If left blank, will default to [_1]</&></i></font>
+<BR><font size="-1"><i><&|/l , $RT::CommentAddress&>(If left blank, will default to [_1])</&></i></font>
</TD>
</TR><TR>
Modified: rt/branches/QUEBEC-EXPERIMENTAL/html/Elements/Error
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/html/Elements/Error (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/html/Elements/Error Wed Jun 8 23:06:16 2005
@@ -53,9 +53,11 @@
<%$Details%>
</font>
<& /Elements/TitleBoxEnd &>
-</body>
-</HTML>
+<%cleanup>
+$m->comp('/Elements/Footer');
+$m->abort();
+</%cleanup>
<%args>
$Code => undef
Modified: rt/branches/QUEBEC-EXPERIMENTAL/html/Search/Build.html
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/html/Search/Build.html (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/html/Search/Build.html Wed Jun 8 23:06:16 2005
@@ -43,6 +43,26 @@
%# 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,
@@ -61,7 +81,7 @@
<table width=100% border="0" cellpadding="5">
<tr valign="top">
<td class="boxcontainer" rowspan="2" width="65%">
-<& Elements/PickCriteria, query => $Query, cfqueues => \%queues &>
+<& Elements/PickCriteria, query => $Query, cfqueues => $queues &>
<& /Elements/Submit, Caption => loc('Add these terms to your search'), Label => loc('Add'), Name => 'AddClause'&>
</td>
@@ -93,7 +113,8 @@
</FORM>
<%INIT>
-use Tree::Simple;
+use RT::Interface::Web::QueryBuilder;
+use RT::Interface::Web::QueryBuilder::Tree;
my $search_hash = {};
my $search;
@@ -157,7 +178,6 @@
# }}}
my @actions = ();
-my %queues;
# Clean unwanted junk from the format
$Format = $m->comp( '/Elements/ScrubHTML', Content => $Format ) if ($Format);
@@ -223,13 +243,9 @@
$m->abort();
}
-my @options;
-my $optionlist;
$Query = "";
-%queues = ();
-# Build the optionlist from the tree, so we can do additions and movements based on it
-$optionlist = build_array( \$Query, \@clauses, $tree, \@options, \%queues );
+my @options = $tree->GetDisplayedNodes;
my @current_values = grep { defined } @options[@clauses];
@@ -296,7 +312,7 @@
Value => $value
};
- my $newnode = Tree::Simple->new($clause);
+ my $newnode = RT::Interface::Web::QueryBuilder::Tree->new($clause);
if (@current_values) {
foreach my $value (@current_values) {
my $newindex = $value->getIndex() + 1;
@@ -386,7 +402,7 @@
my $sibling = $parent->getChild( $index - 1 );
if ( ref( $sibling->getNodeValue ) ) {
$parent->removeChild($value);
- my $newtree = Tree::Simple->new( 'AND', $parent );
+ my $newtree = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $parent );
$newtree->addChild($value);
}
else {
@@ -396,7 +412,7 @@
}
else {
$parent->removeChild($value);
- $newparent = Tree::Simple->new( 'AND', $parent );
+ $newparent = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $parent );
$newparent->addChild($value);
}
}
@@ -431,99 +447,23 @@
push( @actions, [ loc("error: nothing to toggle"), -1 ] );
}
}
-elsif ( $ARGS{"Clear"} ) {
- $tree = Tree::Simple->new( Tree::Simple->ROOT );
-}
+
+$tree->PruneChildlessAggregators;
# }}}
# {{{ Rebuild $Query based on the additions / movements
$Query = "";
- at options = ();
-%queues = ();
-$optionlist =
- build_array( \$Query, \@current_values, $tree, \@options, \%queues );
-
-sub build_array {
- my $Query = shift;
- my $values_ref = shift;
- my $tree = shift;
- my ( $keys, $queues ) = @_;
- my $i = 0;
- my $optionlist;
- my $depth = 0;
- my %parens;
-
- $tree->traverse(
- sub {
- my ($_tree) = @_;
-
- return if $_tree->getParent->isRoot();
-
- push @$keys, $_tree;
- my $clause = $_tree->getNodeValue();
- my $str;
- my $ea = $_tree->getParent()->getNodeValue();
- if ( ref($clause) ) {
- $str .= $ea . " " if $_tree->getIndex() > 0;
- $str .=
- $clause->{Key} . " " . $clause->{Op} . " " . $clause->{Value};
-
- if ( $clause->{Key} eq "Queue" ) {
- $queues->{ $clause->{Value} } = 1;
- }
- }
- else {
- $str = $ea if $_tree->getIndex() > 0;
- }
-
- my $selected;
- if ( grep { $_ == $_tree } @$values_ref ) {
- $selected = "SELECTED";
- }
- else {
- $selected = "";
- }
-
- foreach my $p ( keys %parens ) {
- if ( $p > $_tree->getDepth ) {
- $$Query .= ')' x $parens{$p};
- $parens{$p}--;
- }
- }
-
- $optionlist .=
- "<option value=$i $selected>"
- . ( " " x 5 x ( $_tree->getDepth() - 1 ) )
- . $m->interp->apply_escapes( $str, 'h' )
- . "</option>\n";
- my $parent = $_tree->getParent();
- if ( !( $parent->isRoot || $parent->getParent()->isRoot )
- && !ref( $parent->getNodeValue() ) )
- {
- if ( $_tree->getIndex() == 0 ) {
- $$Query .= '(';
- $parens{ $_tree->getDepth }++;
- }
- }
- $$Query .= " " . $str . " ";
-
- if ( $_tree->getDepth < $depth ) {
- $$Query .= ')';
- $parens{$depth}--;
- }
+my $optionlist_arrayref;
- $i++;
- }
- );
+($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;
- foreach my $p ( keys %parens ) {
- $$Query .= ") " x $parens{$p};
- }
- return $optionlist;
-}
use Regexp::Common qw /delimited/;
@@ -544,8 +484,8 @@
my $depth = 1;
# make a tree root
- $$tree = Tree::Simple->new( Tree::Simple->ROOT );
- my $root = Tree::Simple->new( 'AND', $$tree );
+ $$tree = RT::Interface::Web::QueryBuilder::Tree->new;
+ my $root = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $$tree );
my $lastnode = $root;
my $parentnode = $root;
@@ -618,7 +558,7 @@
$depth++;
# make a new node that the clauses can be children of
- $parentnode = Tree::Simple->new( $ea, $parentnode );
+ $parentnode = RT::Interface::Web::QueryBuilder::Tree->new( $ea, $parentnode );
}
else {
$depth--;
@@ -686,7 +626,7 @@
};
# explicity add a child to it
- $lastnode = Tree::Simple->new( $clause, $parentnode );
+ $lastnode = RT::Interface::Web::QueryBuilder::Tree->new( $clause, $parentnode );
$lastnode->getParent()->setNodeValue($ea);
( $ea, $key, $op, $value ) = ( "", "", "", "" );
@@ -725,11 +665,13 @@
# }}}
+my $queues = $tree->GetReferencedQueues;
+
# {{{ Deal with format changes
my ( $AvailableColumns, $CurrentFormat );
( $Format, $AvailableColumns, $CurrentFormat ) = $m->comp(
'Elements/BuildFormatString',
- cfqueues => \%queues,
+ cfqueues => $queues,
%ARGS, Format => $Format
);
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Action/AutoOpen.pm
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Action/AutoOpen.pm (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Action/AutoOpen.pm Wed Jun 8 23:06:16 2005
@@ -74,6 +74,8 @@
if ( ( $self->TicketObj->Status eq 'open' )
|| ( ( $self->TicketObj->Status eq 'new' )
&& $self->TransactionObj->IsInbound )
+ || ( defined $self->TransactionObj->Message->First
+ && $self->TransactionObj->Message->First->GetHeader('RT-Control') =~ /\bno-autoopen\b/i )
) {
return undef;
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/cs.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/cs.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/cs.po Wed Jun 8 23:06:16 2005
@@ -351,7 +351,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(Pro prázdné pole se použije %1)"
#: html/Admin/Elements/EditCustomFields:74 html/Admin/Elements/ListGlobalCustomFields:53
@@ -4567,8 +4567,8 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
-msgstr "Vzato %1 "
+msgid "Stolen from %1"
+msgstr "Vzato %1"
#: html/Search/Elements/EditFormat:81
msgid "Style"
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/da.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/da.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/da.po Wed Jun 8 23:06:16 2005
@@ -354,8 +354,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "(Hvis ikke angivet vil defaulte til %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Hvis ikke angivet vil defaulte til %1)"
#: html/Admin/Elements/EditCustomFields:74 html/Admin/Elements/ListGlobalCustomFields:53
msgid "(No custom fields)"
@@ -4629,7 +4629,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Stjålet fra %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/de.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/de.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/de.po Wed Jun 8 23:06:16 2005
@@ -3615,8 +3615,8 @@
#. ($Old->Name)
#: lib/RT/Transaction_Overlay.pm:619
-msgid "Stolen from %1 "
-msgstr "Gestohlen von %1 "
+msgid "Stolen from %1"
+msgstr "Gestohlen von %1"
#: html/Elements/QuickCreate:52 html/Elements/SelectAttachmentField:47
#: html/Search/Bulk.html:154 html/SelfService/Create.html:79
@@ -4913,7 +4913,7 @@
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(Standardwert: %1)"
#: html/Admin/Elements/EditCustomFields:74
@@ -8554,8 +8554,8 @@
#. ($Old->Name)
#: lib/RT/Transaction_Overlay.pm:619
-msgid "Stolen from %1 "
-msgstr "Gestohlen von %1 "
+msgid "Stolen from %1"
+msgstr "Gestohlen von %1"
#: html/Elements/QuickCreate:52 html/Elements/SelectAttachmentField:47
#: html/Search/Bulk.html:154 html/SelfService/Create.html:79
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/es.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/es.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/es.po Wed Jun 8 23:06:16 2005
@@ -377,8 +377,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "(Si se deja vacio, pasara por defecto a %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Si se deja vacio, pasara por defecto a %1)"
#: NOT FOUND IN SOURCE
msgid "(No Value)"
@@ -4817,7 +4817,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Robado de %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fi.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fi.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fi.po Wed Jun 8 23:06:16 2005
@@ -362,7 +362,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(Jos jätetään tyhjäksi, palaa arvoon %1)"
#: NOT FOUND IN SOURCE
@@ -4597,7 +4597,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Kaapattu käyttäjältä %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fr.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fr.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/fr.po Wed Jun 8 23:06:16 2005
@@ -379,8 +379,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "Si laissé à blanc, valeur par défaut : %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Si laissé à blanc, valeur par défaut : %1)"
#: NOT FOUND IN SOURCE
msgid "(No Value)"
@@ -4910,7 +4910,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Volé à %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/he.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/he.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/he.po Wed Jun 8 23:06:16 2005
@@ -302,7 +302,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr ""
#: html/Admin/Elements/EditCustomFields:74 html/Admin/Elements/ListGlobalCustomFields:53
@@ -3941,7 +3941,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "נגנב מ %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/hu.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/hu.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/hu.po Wed Jun 8 23:06:16 2005
@@ -268,7 +268,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(Ha üresen marad: %1)"
#: html/Admin/Elements/EditCustomFields:74 html/Admin/Elements/ListGlobalCustomFields:53
@@ -3743,7 +3743,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Probléma elcsenése %1 tulajdonostól"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/it.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/it.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/it.po Wed Jun 8 23:06:16 2005
@@ -110,7 +110,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(se non specificato usa: %1)"
#: NOT FOUND IN SOURCE
@@ -4637,8 +4637,8 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
-msgstr "Sottratto da %1 "
+msgid "Stolen from %1"
+msgstr "Sottratto da %1"
#: html/Search/Elements/EditFormat:81
msgid "Style"
@@ -6248,7 +6248,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(se non specificato usa: %1)"
#: NOT FOUND IN SOURCE
@@ -10807,8 +10807,8 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
-msgstr "Sottratto da %1 "
+msgid "Stolen from %1"
+msgstr "Sottratto da %1"
#: html/Search/Elements/EditFormat:81
msgid "Style"
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ja.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ja.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ja.po Wed Jun 8 23:06:16 2005
@@ -346,7 +346,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr ""
#: html/Admin/Elements/EditCustomFields:74 html/Admin/Elements/ListGlobalCustomFields:53
@@ -4397,7 +4397,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "%1から盗用した"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/nl.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/nl.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/nl.po Wed Jun 8 23:06:16 2005
@@ -348,8 +348,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "(Indien leeggelaten, wordt voorzien van %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Indien leeggelaten, wordt voorzien van %1)"
#: NOT FOUND IN SOURCE
msgid "(No Value)"
@@ -4611,7 +4611,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Gestolen van %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/no.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/no.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/no.po Wed Jun 8 23:06:16 2005
@@ -380,7 +380,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(Settes til standard %1 hvis blank)"
#: NOT FOUND IN SOURCE
@@ -4887,8 +4887,8 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
-msgstr "Stjålet fra %1 "
+msgid "Stolen from %1"
+msgstr "Stjålet fra %1"
#: html/Search/Elements/EditFormat:81
msgid "Style"
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pl.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pl.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pl.po Wed Jun 8 23:06:16 2005
@@ -386,8 +386,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "(Jeśli pozostawisz puste, domyślnie zostanie ustawione na %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Jeśli pozostawisz puste, domyślnie zostanie ustawione na %1)"
#: NOT FOUND IN SOURCE
msgid "(No Value)"
@@ -5112,7 +5112,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Przejęte od %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pt_br.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pt_br.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/pt_br.po Wed Jun 8 23:06:16 2005
@@ -377,8 +377,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "(Se deixado em branco, será entendido como %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Se deixado em branco, será entendido como %)"
#: NOT FOUND IN SOURCE
msgid "(No Value)"
@@ -4860,8 +4860,8 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
-msgstr "Roubado de %1 "
+msgid "Stolen from %1"
+msgstr "Roubado de %1"
#: html/Search/Elements/EditFormat:81
msgid "Style"
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ru.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ru.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/ru.po Wed Jun 8 23:06:16 2005
@@ -368,8 +368,8 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
-msgstr "(Если пустое, то по-умолчанию равно %1"
+msgid "(If left blank, will default to %1)"
+msgstr "(Если пустое, то по-умолчанию равно %1)"
#: NOT FOUND IN SOURCE
msgid "(No Value)"
@@ -4960,7 +4960,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "Ответственный переназначен с %1"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_cn.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_cn.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_cn.po Wed Jun 8 23:06:16 2005
@@ -405,7 +405,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(如果留白, 则预设为 %1)"
#: NOT FOUND IN SOURCE
@@ -6376,7 +6376,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "承办人从 %1 强制更换"
#: html/Search/Elements/EditFormat:81
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_tw.po
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_tw.po (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/I18N/zh_tw.po Wed Jun 8 23:06:16 2005
@@ -405,7 +405,7 @@
#: html/Admin/Queues/Modify.html:75 html/Admin/Queues/Modify.html:81
#. ($RT::CorrespondAddress)
#. ($RT::CommentAddress)
-msgid "(If left blank, will default to %1"
+msgid "(If left blank, will default to %1)"
msgstr "(如果留白, 則預設為 %1)"
#: NOT FOUND IN SOURCE
@@ -6376,7 +6376,7 @@
#: lib/RT/Transaction_Overlay.pm.orig:665 lib/RT/Transaction_Overlay.pm:665
#. ($Old->Name)
-msgid "Stolen from %1 "
+msgid "Stolen from %1"
msgstr "承辦人從 %1 強制更換"
#: html/Search/Elements/EditFormat:81
Added: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder.pm
==============================================================================
--- (empty file)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder.pm Wed Jun 8 23:06:16 2005
@@ -0,0 +1,56 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# 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 }}}
+package RT::Interface::Web::QueryBuilder;
+
+use strict;
+use warnings;
+
+eval "require RT::Interface::Web::QueryBuilder_Vendor";
+die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder_Vendor.pm});
+eval "require RT::Interface::Web::QueryBuilder_Local";
+die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder_Local.pm});
+
+1;
Added: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder/Tree.pm
==============================================================================
--- (empty file)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Interface/Web/QueryBuilder/Tree.pm Wed Jun 8 23:06:16 2005
@@ -0,0 +1,245 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# <jesse at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# 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 }}}
+package RT::Interface::Web::QueryBuilder::Tree;
+
+use strict;
+use warnings;
+
+use base qw/Tree::Simple/;
+
+=head1 NAME
+
+ RT::Interface::Web::QueryBuilder::Tree - subclass of Tree::Simple used in Query Builder
+
+=head1 DESCRIPTION
+
+This class provides support functionality for the Query Builder (Search/Build.html).
+It is a subclass of L<Tree::Simple>.
+
+=head1 METHODS
+
+=head2 TraversePrePost PREFUNC POSTFUNC
+
+Traverses the tree depth-first. Before processing the node's children,
+calls PREFUNC with the node as its argument; after processing all of the
+children, calls POSTFUNC with the node as its argument.
+
+(Note that unlike Tree::Simple's C<traverse>, it actually calls its functions
+on the root node passed to it.)
+
+=cut
+
+sub TraversePrePost {
+ my ($self, $prefunc, $postfunc) = @_;
+
+ $prefunc->($self);
+
+ foreach my $child ($self->getAllChildren()) {
+ $child->TraversePrePost($prefunc, $postfunc);
+ }
+
+ $postfunc->($self);
+}
+
+=head2 GetReferencedQueues
+
+Returns a hash reference with keys each queue name referenced in a clause in
+the key (even if it's "Queue != 'Foo'"), and values all 1.
+
+=cut
+
+sub GetReferencedQueues {
+ my $self = shift;
+
+ my $queues = {};
+
+ $self->traverse(
+ sub {
+ my $node = shift;
+
+ return if $node->isRoot;
+
+ my $clause = $node->getNodeValue();
+
+ if ( ref($clause) and $clause->{Key} eq 'Queue' ) {
+ $queues->{ $clause->{Value} } = 1;
+ };
+ }
+ );
+
+ return $queues;
+}
+
+=head2 GetQueryAndOptionList SELECTED_NODES
+
+Given an array reference of tree nodes that have been selected by the user,
+traverses the tree and returns the equivalent SQL query and a list of hashes
+representing the "clauses" select option list. Each has contains the keys
+TEXT, INDEX, SELECTED, and DEPTH. TEXT is the displayed text of the option
+(including parentheses, not including indentation); INDEX is the 0-based
+index of the option in the list (also used as its CGI parameter); SELECTED
+is either 'SELECTED' or '', depending on whether the node corresponding
+to the select option was in the SELECTED_NODES list; and DEPTH is the
+level of indentation for the option.
+
+=cut
+
+sub GetQueryAndOptionList {
+ my $self = shift;
+ my $selected_nodes = shift;
+
+ my $optionlist = [];
+
+ my $i = 0;
+
+ $self->TraversePrePost(
+ sub { # This is called before recursing to the node's children.
+ my $node = shift;
+
+ return if $node->isRoot or $node->getParent->isRoot;
+
+ my $clause = $node->getNodeValue();
+ my $str = ' ';
+ my $aggregator_context = $node->getParent()->getNodeValue();
+ $str = $aggregator_context . " " if $node->getIndex() > 0;
+
+ if ( ref($clause) ) { # ie, it's a leaf
+ $str .=
+ $clause->{Key} . " " . $clause->{Op} . " " . $clause->{Value};
+ }
+
+ unless ($node->getParent->getParent->isRoot) {
+ # used to check !ref( $parent->getNodeValue() ) )
+ if ( $node->getIndex() == 0 ) {
+ $str = '( ' . $str;
+ }
+ }
+
+ push @$optionlist, {
+ TEXT => $str,
+ INDEX => $i,
+ SELECTED => (grep { $_ == $node } @$selected_nodes) ? 'SELECTED' : '',
+ DEPTH => $node->getDepth() - 1,
+ };
+
+ $i++;
+ }, sub {
+ # This is called after recursing to the node's children.
+ my $node = shift;
+
+ return if $node->isRoot or $node->getParent->isRoot or $node->getParent->getParent->isRoot;
+
+ # Only do this for the rightmost child.
+ return unless $node->getIndex == $node->getParent->getChildCount - 1;
+
+ $optionlist->[-1]{TEXT} .= ' )';
+ }
+ );
+
+ return (join ' ', map { $_->{TEXT} } @$optionlist), $optionlist;
+}
+
+=head2 PruneChildLessAggregators
+
+If tree manipulation has left it in a state where there are ANDs, ORs,
+or parenthesizations with no children, get rid of them.
+
+=cut
+
+sub PruneChildlessAggregators {
+ my $self = shift;
+
+ $self->TraversePrePost(
+ sub {
+ },
+ sub {
+ my $node = shift;
+
+ return if $node->isRoot or $node->getParent->isRoot;
+
+ # We're only looking for aggregators (AND/OR)
+ return if ref $node->getNodeValue;
+
+ return if $node->getChildCount != 0;
+
+ # OK, this is a childless aggregator. Remove self.
+
+ $node->getParent->removeChild($node);
+
+ # Deal with circular refs
+ $node->DESTROY;
+ }
+ );
+}
+
+=head2 GetDisplayedNodes
+
+This function returns a list of the nodes of the tree in depth-first
+order which correspond to options in the "clauses" multi-select box.
+In fact, it's all of them but the root and its child.
+
+=cut
+
+sub GetDisplayedNodes {
+ my $self = shift;
+ my @lines;
+
+ $self->traverse(sub {
+ my $node = shift;
+
+ push @lines, $node unless $node->isRoot or $node->getParent->isRoot;
+ });
+
+ return @lines;
+}
+
+
+eval "require RT::Interface::Web::QueryBuilder::Tree_Vendor";
+die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder/Tree_Vendor.pm});
+eval "require RT::Interface::Web::QueryBuilder::Tree_Local";
+die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Web/QueryBuilder/Tree_Local.pm});
+
+1;
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/RT/Transaction_Overlay.pm Wed Jun 8 23:06:16 2005
@@ -662,7 +662,7 @@
my $self = shift;
my $Old = RT::User->new( $self->CurrentUser );
$Old->Load( $self->OldValue );
- return $self->loc("Stolen from [_1] ", $Old->Name);
+ return $self->loc("Stolen from [_1]", $Old->Name);
},
Give => sub {
my $self = shift;
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/02basic_web.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/02basic_web.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/02basic_web.t Wed Jun 8 23:06:16 2005
@@ -1,7 +1,7 @@
#!/usr/bin/perl
use strict;
-use Test::More 'no_plan';
+use Test::More tests => 17;
use WWW::Mechanize;
use HTTP::Request::Common;
use HTTP::Cookies;
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/04send_email.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/04send_email.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/04send_email.t Wed Jun 8 23:06:16 2005
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
use strict;
-use Test::More qw/no_plan/;
+use Test::More tests => 137;
use RT;
RT::LoadConfig();
RT::Init;
@@ -50,6 +50,7 @@
$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC');
$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0');
my $tick= $tickets->First();
+isa_ok($tick, "RT::Ticket", "got a ticket object");
ok ($tick->Id, "found ticket ".$tick->Id);
ok ($tick->Transactions->First->Content =~ /The original message was received/, "It's the bounce");
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/09record_cf_api.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/09record_cf_api.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/09record_cf_api.t Wed Jun 8 23:06:16 2005
@@ -2,7 +2,7 @@
use strict;
#use warnings FATAL => 'all';
-use Test::More qw/no_plan/;
+use Test::More tests => 130;
use RT;
RT::LoadConfig();
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/10merge.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/10merge.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/10merge.t Wed Jun 8 23:06:16 2005
@@ -8,7 +8,7 @@
# This test script validates that when merging two tickets, the comments from both tickets
# are integrated into the new ticket
-use Test::More qw/no_plan/;
+use Test::More tests => 13;
use RT;
RT::LoadConfig;
RT::Init;
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/11-template-insert.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/11-template-insert.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/11-template-insert.t Wed Jun 8 23:06:16 2005
@@ -3,7 +3,7 @@
use warnings;
use strict;
-use Test::More qw/no_plan/;
+use Test::More tests => 7;
use RT;
RT::LoadConfig();
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/12-search.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/12-search.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/12-search.t Wed Jun 8 23:06:16 2005
@@ -6,7 +6,7 @@
use strict;
use warnings;
-use Test::More qw/no_plan/;
+use Test::More tests => 35;
use_ok('RT');
RT::LoadConfig();
RT::Init();
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/13-attribute-tests.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/13-attribute-tests.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/13-attribute-tests.t Wed Jun 8 23:06:16 2005
@@ -1,5 +1,5 @@
-use Test::More qw/no_plan/;
+use Test::More tests => 24;
use RT;
RT::LoadConfig();
RT::Init();
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/15cf_single_values_are_single.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/15cf_single_values_are_single.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/15cf_single_values_are_single.t Wed Jun 8 23:06:16 2005
@@ -1,7 +1,7 @@
#!/usr/bin/perl
use warnings;
use strict;
-use Test::More qw/no_plan/;
+use Test::More tests => 8;
use RT;
RT::LoadConfig();
Modified: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/20savedsearch.t
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/20savedsearch.t (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/20savedsearch.t Wed Jun 8 23:06:16 2005
@@ -1,5 +1,5 @@
use RT;
-use Test::More qw/no_plan/;
+use Test::More tests => 26;
use RT::User;
use RT::Group;
use RT::Ticket;
Added: rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/21query-builder.t
==============================================================================
--- (empty file)
+++ rt/branches/QUEBEC-EXPERIMENTAL/lib/t/regression/21query-builder.t Wed Jun 8 23:06:16 2005
@@ -0,0 +1,204 @@
+#!/usr/bin/perl
+
+use strict;
+use Test::More tests => 31;
+use Test::WWW::Mechanize;
+use HTTP::Request::Common;
+use HTTP::Cookies;
+use LWP;
+use Encode;
+
+my $cookie_jar = HTTP::Cookies->new;
+my $agent = Test::WWW::Mechanize->new();
+
+# give the agent a place to stash the cookies
+
+$agent->cookie_jar($cookie_jar);
+
+use RT;
+RT::LoadConfig;
+
+# get the top page
+my $url = $RT::WebURL;
+$agent->get($url);
+
+is ($agent->{'status'}, 200, "Loaded a page");
+
+
+# {{{ test a login
+
+# follow the link marked "Login"
+
+ok($agent->{form}->find_input('user'));
+
+ok($agent->{form}->find_input('pass'));
+ok ($agent->{'content'} =~ /username:/i);
+$agent->field( 'user' => 'root' );
+$agent->field( 'pass' => 'password' );
+# the field isn't named, so we have to click link 0
+$agent->click(0);
+is($agent->{'status'}, 200, "Fetched the page ok");
+ok( $agent->{'content'} =~ /Logout/i, "Found a logout link");
+
+# }}}
+
+# {{{ Query Builder tests
+
+my $response = $agent->get($url."Search/Build.html");
+ok( $response->is_success, "Fetched " . $url."Search/Build.html" );
+
+# Adding items
+
+# set the first value
+ok($agent->form_name('BuildQuery'), "found the form once");
+$agent->field("ActorField", "Owner");
+$agent->field("ActorOp", "=");
+$agent->field("ValueOfActor", "Nobody");
+$agent->submit();
+
+# set the next value
+ok($agent->form_name('BuildQuery'), "found the form again");
+$agent->field("QueueOp", "!=");
+$agent->field("ValueOfQueue", "Regression");
+$agent->submit();
+
+ok($agent->form_name('BuildQuery'), "found the form a third time");
+
+sub getQueryFromForm {
+ # This pulls out the "hidden input" query from the page
+ my $q = $agent->current_form->find_input("Query")->value;
+ $q =~ s/^\s+//g;
+ $q =~ s/\s+$//g;
+ $q =~ s/\s+/ /g;
+ return $q;
+}
+
+is (getQueryFromForm, "Owner = 'Nobody' AND Queue != 'Regression'");
+
+# We're going to delete the owner
+
+$agent->select("clauses", ["0"] );
+
+$agent->click("DeleteClause");
+
+ok($agent->form_name('BuildQuery'), "found the form a fourth time");
+
+is (getQueryFromForm, "Queue != 'Regression'");
+
+$agent->field("AndOr", "OR");
+
+$agent->select("idOp", ">");
+
+$agent->field("ValueOfid" => "1234");
+
+$agent->click("AddClause");
+
+ok($agent->form_name('BuildQuery'), "found the form again");
+TODO: {
+ local $TODO = "query builder incorrectly quotes numbers";
+ is(getQueryFromForm, "Queue != 'Regression' OR id > 1234", "added something as OR, and number not quoted");
+}
+
+sub selectedClauses {
+ my @clauses = grep { defined } map { $_->value } $agent->current_form->find_input("clauses");
+ return [ @clauses ];
+}
+
+
+is_deeply(selectedClauses, ["1"], 'the id that we just entered is still selected');
+
+# Move the second one up a level
+$agent->click("Up");
+
+ok($agent->form_name('BuildQuery'), "found the form again");
+is(getQueryFromForm, "id > 1234 OR Queue != 'Regression'", "moved up one");
+
+is_deeply(selectedClauses, ["0"], 'the one we moved up is selected');
+
+$agent->click("Right");
+
+ok($agent->form_name('BuildQuery'), "found the form again");
+is(getQueryFromForm, "Queue != 'Regression' OR ( id > 1234 )", "moved over to the right (and down)");
+is_deeply(selectedClauses, ["2"], 'the one we moved right is selected');
+
+$agent->select("clauses", ["1"]);
+
+$agent->click("Up");
+
+ok($agent->form_name('BuildQuery'), "found the form again");
+TODO: {
+ local $TODO = "query builder incorrectly changes OR to AND";
+ is(getQueryFromForm, "( id > 1234 ) OR Queue != 'Regression'", "moved up");
+}
+
+$agent->select("clauses", ["0"]); # this is a null clause
+
+$agent->click("Up");
+
+ok($agent->form_name('BuildQuery'), "found the form again");
+
+$agent->content_like(qr/error: can\S+t move up/, "i shouldn't have been able to hit up");
+
+$agent->click("Left");
+
+ok($agent->form_name('BuildQuery'), "found the form again");
+
+$agent->content_like(qr/error: can\S+t move left/, "i shouldn't have been able to hit left");
+
+$agent->select("clauses", ["1"]);
+$agent->select("ValueOfStatus" => "stalled");
+
+$agent->submit;
+ok($agent->form_name('BuildQuery'), "found the form again");
+is_deeply(selectedClauses, ["2"], 'the one we added is selected');
+TODO: {
+ local $TODO = "query builder incorrectly changes OR to AND";
+ is(getQueryFromForm, "( id > 1234 AND Status = 'stalled' ) OR Queue != 'Regression'", "added new one");
+}
+
+
+
+# - new items go one level down
+# - add items at currently selected level
+# - if nothing is selected, add at end, one level down
+#
+# move left
+# - error if nothing selected
+# - same item should be selected after move
+# - can't move left if you're at the top level
+#
+# move right
+# - error if nothing selected
+# - same item should be selected after move
+# - can always move right (no max depth...should there be?)
+#
+# move up
+# - error if nothing selected
+# - same item should be selected after move
+# - can't move up if you're first in the list
+#
+# move down
+# - error if nothing selected
+# - same item should be selected after move
+# - can't move down if you're last in the list
+#
+# toggle
+# - error if nothing selected
+# - change all aggregators in the grouping
+# - don't change any others
+#
+# delete
+# - error if nothing selected
+# - delete currently selected item
+# - delete all children of a grouping
+# - if delete leaves a node with no children, delete that, too
+# - what should be selected?
+#
+# Clear
+# - clears entire query
+# - clears it from the session, too
+
+# }}}
+
+
+1;
Modified: rt/branches/QUEBEC-EXPERIMENTAL/sbin/rt-test-dependencies.in
==============================================================================
--- rt/branches/QUEBEC-EXPERIMENTAL/sbin/rt-test-dependencies.in (original)
+++ rt/branches/QUEBEC-EXPERIMENTAL/sbin/rt-test-dependencies.in Wed Jun 8 23:06:16 2005
@@ -52,7 +52,6 @@
use strict;
no warnings qw(numeric redefine);
use Getopt::Long;
-use CPAN;
my %args;
my %deps;
GetOptions(
@@ -80,8 +79,43 @@
$args{'with-DEV'} =1;
$args{'with-CLI'} =1;
$args{'with-MAILGATE'} =1;
-
-
+{
+ my $section;
+ my %always_show_sections = (
+ perl => 1,
+ users => 1,
+ );
+
+ sub section {
+ my $s = shift;
+ $section = $s;
+ print "$s:\n";
+ }
+
+ my $any_missing = 0;
+ sub found {
+ my $msg = shift;
+ my $test = shift;
+ my $extra = shift;
+
+ $any_missing = 1 unless $test;
+ if ($args{'v'} or not $test or $always_show_sections{$section}) {
+ print "\t$msg...";
+ print $test ? "found" : "MISSING";
+ print "\n";
+ }
+
+ print "\t\t$extra\n" if defined $extra;
+ }
+
+ sub conclude {
+ if ($any_missing) {
+ print "\nSOMETHING WAS MISSING!\n";
+ } else {
+ print "\nEverything was found.\n";
+ }
+ }
+}
sub help {
@@ -243,7 +277,7 @@
foreach my $type (keys %args) {
next unless ($type =~ /^with-(.*?)$/);
my $type = $1;
- print "$type dependencies:\n";
+ section("$type dependencies");
my @deps = (@{$deps{$type}});
while (@deps) {
my $module = shift @deps;
@@ -256,6 +290,8 @@
}
}
+conclude();
+
sub test_dep {
my $module = shift;
my $version = shift;
@@ -264,26 +300,25 @@
if ($@) {
my $error = $@;
$error =~ s/\n(.*)$//s;
- print "\t$module $version";
- print "...MISSING\n";
- print "\t\t$error\n" if $error =~ /this is only/;
+ undef $error unless $error =~ /this is only/;
+ found("$module $version", 0, $error);
return undef;
} else {
- print "\t$module $version...found\n" if $args{'v'};
+ found("$module $version", 1);
return 1;
}
}
sub resolve_dep {
my $module = shift;
- use CPAN;
- CPAN::Shell->install($module);
+ system( qq[@PERL@ -MCPAN -e'install("$module")'] );
}
sub download_mods {
my %modules;
-
+ use CPAN;
+
foreach my $key (keys %deps) {
my @deps = (@{$deps{$key}});
while (@deps) {
@@ -322,38 +357,24 @@
}
sub check_perl_version {
-
-
-print "perl:\n";
-print "\t5.8.3";
-eval {require 5.008003};
-if ($@) {
- print "...MISSING.\n";
- eval {require 5.008000};
- if ($@) {
- print "\nRT is known to be non-functional on versions of perl older than 5.8.3.\nPlease upgrade to 5.8.3 or newer\n\n";
- die;
- }
-
- eval {require 5.008003};
- if ($@) {
- print "\nRT is known to be non-functional on versions of perl older than 5.8.3.\nPlease upgrade to 5.8.3 or newer\n\n";
- }
-} else {
- print "...found\n" if $args{'v'};
-}
+ section("perl");
+ eval {require 5.008003};
+ if ($@) {
+ found("5.8.3", 0, "RT is known to be non-functional on versions of perl older than 5.8.3. Please upgrade to 5.8.3 or newer.");
+ die;
+ } else {
+ found("5.8.3", 1);
+ }
}
sub check_users {
-
-print "users:\n";
-print "\trt group (@RTGROUP@)...", (defined getgrnam("@RTGROUP@") ? "found" : "MISSING"), "\n";
-print "\tbin owner (@BIN_OWNER@)...", (defined getpwnam("@BIN_OWNER@") ? "found" : "MISSING"), "\n";
-print "\tlibs owner (@LIBS_OWNER@)...", (defined getpwnam("@LIBS_OWNER@") ? "found" : "MISSING"), "\n";
-print "\tlibs group (@LIBS_GROUP@)...", (defined getgrnam("@LIBS_GROUP@") ? "found" : "MISSING"), "\n";
-print "\tweb owner (@WEB_USER@)...", (defined getpwnam("@WEB_USER@") ? "found" : "MISSING"), "\n";
-print "\tweb group (@WEB_GROUP@)...", (defined getgrnam("@WEB_GROUP@") ? "found" : "MISSING"), "\n";
-
+ section("users");
+ found("rt group (@RTGROUP@)", defined getgrnam("@RTGROUP@"));
+ found("bin owner (@BIN_OWNER@)", defined getpwnam("@BIN_OWNER@"));
+ found("libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@"));
+ found("libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@"));
+ found("web owner (@WEB_USER@)", defined getpwnam("@WEB_USER@"));
+ found("web group (@WEB_GROUP@)", defined getgrnam("@WEB_GROUP@"));
}
More information about the Rt-commit
mailing list