[Rt-commit] r3045 - in rt/branches/3.4-RELEASE: . html/Search lib/RT/Interface/Web lib/RT/Interface/Web/QueryBuilder

glasser at bestpractical.com glasser at bestpractical.com
Wed Jun 1 18:35:35 EDT 2005


Author: glasser
Date: Wed Jun  1 18:35:33 2005
New Revision: 3045

Added:
   rt/branches/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder/
   rt/branches/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder.pm   (contents, props changed)
   rt/branches/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder/Tree.pm   (contents, props changed)
Modified:
   rt/branches/3.4-RELEASE/   (props changed)
   rt/branches/3.4-RELEASE/html/Search/Build.html
Log:
 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.


Modified: rt/branches/3.4-RELEASE/html/Search/Build.html
==============================================================================
--- rt/branches/3.4-RELEASE/html/Search/Build.html	(original)
+++ rt/branches/3.4-RELEASE/html/Search/Build.html	Wed Jun  1 18:35:33 2005
@@ -61,7 +61,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 additional criteria'), Label => loc('Add'), Name => 'AddClause'&>
 </td>
 
@@ -96,7 +96,8 @@
 </FORM>
 
 <%INIT>
-use Tree::Simple;
+use RT::Interface::Web::QueryBuilder;
+use RT::Interface::Web::QueryBuilder::Tree;
 
 my $search_hash = {};
 my $search;
@@ -146,7 +147,6 @@
 # }}}
 
 my @actions = ();
-my %queues;
 
 # Clean unwanted junk from the format
 $Format = $m->comp( '/Elements/ScrubHTML', Content => $Format ) if ($Format);
@@ -246,7 +246,6 @@
 }
 
 $Query  = "";
-%queues = ();
 
 my @options = get_displayed_nodes($tree);
 
@@ -315,7 +314,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;
@@ -405,7 +404,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 {
@@ -415,7 +414,7 @@
             }
             else {
                 $parent->removeChild($value);
-                $newparent = Tree::Simple->new( 'AND', $parent );
+                $newparent = RT::Interface::Web::QueryBuilder::Tree->new( 'AND', $parent );
                 $newparent->addChild($value);
             }
         }
@@ -451,16 +450,23 @@
     }
 }
 elsif ( $ARGS{"Clear"} ) {
-    $tree = Tree::Simple->new( Tree::Simple->ROOT );
+    $tree = RT::Interface::Web::QueryBuilder::Tree->new;
 }
 
 # }}}
 
 # {{{ Rebuild $Query based on the additions / movements
 $Query      = "";
-%queues     = ();
-my $optionlist =
-  build_array( \$Query, \@current_values, $tree, \%queues );
+my($optionlist_arrayref, $queues);
+
+($optionlist_arrayref, $Query, $queues) =
+  RT::Interface::Web::QueryBuilder::TreeToQueryAndOptionListAndQueues( $tree, \@current_values );
+  
+my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) 
+                                  . ("&nbsp;" x (5 * $_->{DEPTH}))
+                                  . $m->interp->apply_escapes($_->{TEXT}, 'h') . qq(</option>) } @$optionlist_arrayref;
+
+
 
 # This function returns an array ref of the nodes of the tree in depth-first
 # order which correspond to options in the "clauses" multi-select box.
@@ -478,112 +484,6 @@
     return @keys;
 }
 
-sub build_array {
-    my $Query      = shift;
-    my $values_ref = shift;
-    my $tree       = shift;
-    my $queues     = shift;
-    
-    my $i = 0;
-    my @optionlist;
-    my $depth = 0;
-    my %parens;
-
-    $tree->traverse(
-        sub {
-            my ($_tree) = @_;
-
-            return if $_tree->getParent->isRoot();
-
-            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 = "";
-            }
-            
-            # These two variables are for display in the optionlists only.
-            my $before_parens = '';
-            my $after_parens = '';
-
-            foreach my $p ( keys %parens ) {
-                if ( $p > $_tree->getDepth ) {
-                    $$Query .= ')' x $parens{$p};
-                    # The fact that I am writing this line implies
-                    # that the whole function should be rewritten, because
-                    # it ought to be possible to have figured out this
-                    # information earlier:
-                    $optionlist[-1]{TEXT} .= ')' x $parens{$p};
-                    $parens{$p}--;
-                }
-            }
-
-            my $parent = $_tree->getParent();
-            if (   !( $parent->isRoot || $parent->getParent()->isRoot )
-                && !ref( $parent->getNodeValue() ) )
-            {
-                if ( $_tree->getIndex() == 0 ) {
-                    $$Query .= '(';
-                    $before_parens .= '(';
-                    $parens{ $_tree->getDepth }++;
-                }
-            }
-            $$Query .= " " . $str . " ";
-
-            if ( $_tree->getDepth < $depth ) {
-                $$Query .= ')';
-                $after_parens .= ')';
-                $parens{$depth}--;
-            }
-            
-            push @optionlist, {
-                TEXT     => $before_parens . $str . $after_parens,
-                INDEX    => $i,
-                SELECTED => $selected,
-                DEPTH    => $_tree->getDepth() - 1,
-            };
-
-            $i++;
-        }
-    );
-
-    foreach my $p ( keys %parens ) {
-        $$Query .= ") " x $parens{$p};
-        $optionlist[-1]{TEXT} .= ") " x $parens{$p};
-    }
-    
-    my $should_be_query = join ' ', map { $_->{TEXT} } @optionlist;
-    
-#   So, $should_be_query *ought* to be the same as $$Query but calculated in a much
-#   simpler way, but this has not been tested enough to make sure, so I won't commit it. 
-#   my $sbq_tmp = $should_be_query;
-#   my $q_tmp = $$Query;
-#   $sbq_tmp =~ tr/ //d; $q_tmp =~ tr/ //d;
-#   $RT::Logger->crit("query check: " . ($q_tmp eq $sbq_tmp ? 'yay' : 'nay') );
-
-    return join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}>) 
-                            . ("&nbsp;" x (5 * $_->{DEPTH}))
-                            . $m->interp->apply_escapes($_->{TEXT}, 'h') . qq(</option>) } @optionlist;
-
-}
-
 use Regexp::Common qw /delimited/;
 
 # States
@@ -603,8 +503,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;
 
@@ -677,7 +577,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--;
@@ -745,7 +645,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 ) = ( "", "", "", "" );
@@ -788,7 +688,7 @@
 my ( $AvailableColumns, $CurrentFormat );
 ( $Format, $AvailableColumns, $CurrentFormat ) = $m->comp(
     'Elements/BuildFormatString',
-    cfqueues => \%queues,
+    cfqueues => $queues,
     %ARGS, Format => $Format
 );
 

Added: rt/branches/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder.pm
==============================================================================
--- (empty file)
+++ rt/branches/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder.pm	Wed Jun  1 18:35:33 2005
@@ -0,0 +1,135 @@
+# 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;
+
+sub TreeToQueryAndOptionListAndQueues {
+    my $tree           = shift;
+    my $selected_nodes = shift;
+    
+    my $Query = '';
+    my $queues = {};
+    my $optionlist = [];
+
+    my $i = 0;
+
+    $tree->traverse_pre_post(
+        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};
+
+                if ( $clause->{Key} eq "Queue" ) {
+                    $queues->{ $clause->{Value} } = 1;
+                }
+            }
+
+            my $selected = '';
+            if ( grep { $_ == $node } @$selected_nodes ) {
+                $selected = "SELECTED";
+            }
+
+            unless ($node->getParent->getParent->isRoot) {
+        #        used to check !ref( $parent->getNodeValue() ) )
+                if ( $node->getIndex() == 0 ) {
+                    $str = '( ' . $str;
+                }
+            }
+            
+            $Query .= " " . $str . " ";
+
+            push @$optionlist, {
+                TEXT     => $str,
+                INDEX    => $i,
+                SELECTED => $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;
+            
+            $Query .= ' )';
+            $optionlist->[-1]{TEXT} .= ' )';
+        }
+    );
+
+    my $should_be_query = join ' ', map { $_->{TEXT} } @$optionlist;
+
+#   So, $should_be_query *ought* to be the same as $Query but calculated in a much
+#   simpler way, but this has not been tested enough to make sure, so I won't commit it. 
+#   my $sbq_tmp = $should_be_query;
+#   my $q_tmp = $Query;
+#   $sbq_tmp =~ tr/ //d; $q_tmp =~ tr/ //d;
+#   $RT::Logger->crit("query check: " . ($q_tmp eq $sbq_tmp ? 'yay' : 'nay') );
+
+    return $optionlist, $Query, $queues;
+}
+
+
+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/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder/Tree.pm
==============================================================================
--- (empty file)
+++ rt/branches/3.4-RELEASE/lib/RT/Interface/Web/QueryBuilder/Tree.pm	Wed Jun  1 18:35:33 2005
@@ -0,0 +1,79 @@
+# 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/;
+
+=head2 traverse_pre_post 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.
+
+=cut
+
+sub traverse_pre_post {
+   my ($self, $prefunc, $postfunc) = @_;
+
+   $prefunc->($self);
+   
+   foreach my $child ($self->getAllChildren()) { 
+           $child->traverse_pre_post($prefunc, $postfunc);
+   }
+   
+   $postfunc->($self);
+}
+
+
+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;


More information about the Rt-commit mailing list