[Rt-commit] rt branch, googleish-refactor, updated. rt-3.8.5-206-gf545b34

sunnavy at bestpractical.com sunnavy at bestpractical.com
Wed Sep 30 21:16:37 EDT 2009


The branch, googleish-refactor has been updated
       via  f545b3456d48ae265778c9f643e092c3d3f6d6ba (commit)
      from  43adaaf5fc05d5c0beccf5767521ecd0547be821 (commit)

Summary of changes:
 etc/RT_Config.pm.in            |   22 ++++
 lib/RT/Search/Googleish.pm     |  258 ++++++++++++++++++++++++++++-----------
 share/html/Search/Results.html |    6 +
 3 files changed, 213 insertions(+), 73 deletions(-)

- Log -----------------------------------------------------------------
commit f545b3456d48ae265778c9f643e092c3d3f6d6ba
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Oct 1 09:15:48 2009 +0800

    1. option to auto redirect to the ticket display page if found only 1 ticket.
    2. option to search all the tickets( including resolved ones )
    3. new syntax like cf.foo:bar status:new
    4. refactor QueryToSQL to make it not so *huge*

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 4943769..12fa450 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1260,6 +1260,28 @@ Set($DefaultTimeUnitsToHours, 0);
 
 =back
 
+=item C<$SearchResultsAutoRedirect>
+
+when only one ticket is found in search, use this to redirect to the ticket
+display page automatically.
+
+=cut
+
+Set($SearchResultsAutoRedirect, 0);
+
+=back
+
+=item C<$OnlySearchActiveTicketsInSimpleSearch>
+
+When query in simple search doesn't have status info,
+use this to only search active ones.
+
+=cut
+
+Set($OnlySearchActiveTicketsInSimpleSearch, 1);
+
+=back
+
 =head1 L<Net::Server> (rt-server) Configuration
 
 =over 4
diff --git a/lib/RT/Search/Googleish.pm b/lib/RT/Search/Googleish.pm
index 07e1904..87270e6 100644
--- a/lib/RT/Search/Googleish.pm
+++ b/lib/RT/Search/Googleish.pm
@@ -96,108 +96,220 @@ sub QueryToSQL {
     my $query    = shift || $self->Argument;
 
     my @keywords = grep length, map { s/^\s+//; s/\s+$//; $_ }
-        split /((?:fulltext:)?$re_delim|\s+)/o, $query;
+      split /((?:fulltext:)?$re_delim|\s+)/o, $query;
 
     my (
-        @tql_clauses,  @owner_clauses, @queue_clauses,
-        @user_clauses, @id_clauses,    @status_clauses
+        @keyvalue_clauses, @number_clauses, @status_clauses,
+        @queue_clauses,    @user_clauses,   @owner_clauses,
+        @others_clauses,   @tql_clauses
     );
-    my ( $Queue, $User );
-    for my $key (@keywords) {
 
-        # Is this a ticket number? If so, go to it.
-        # But look into subject as well
-        if ( $key =~ m/^\d+$/ ) {
-            push @id_clauses, "id = '$key'", "Subject LIKE '$key'";
-        }
+    my %map = (
+        KeyValue => \@keyvalue_clauses,
+        Number   => \@number_clauses,
+        Status   => \@status_clauses,
+        Queue    => \@queue_clauses,
+        User     => \@user_clauses,
+        Owner    => \@owner_clauses,
+        Others   => \@others_clauses
+    );
 
-        # if it's quoted string then search it "as is" in subject or fulltext
-        elsif ( $key =~ /^(fulltext:)?($re_delim)$/io ) {
-            if ( $1 ) {
-                push @tql_clauses, "Content LIKE $2";
-            } else {
-                push @tql_clauses, "Subject LIKE $2";
+  KEYWORD:
+    for my $keyword (@keywords) {
+        for my $action (qw/KeyValue Number User Status Queue Owner Others/) {
+            my $translate = 'Translate' . $action;
+            my $clause    = $map{$action};
+            my @clauses   = $self->$translate($keyword);
+            if (@clauses) {
+                push @{$clause}, @clauses;
+                next KEYWORD;
             }
         }
+    }
 
-        elsif ( $key =~ /^fulltext:(.*?)$/i ) {
-            $key = $1;
-            $key =~ s/['\\].*//g;
-            push @tql_clauses, "Content LIKE '$key'";
+    $self->ProcessAfterTranslate(
+        key_value => \@keyvalue_clauses,
+        number    => \@number_clauses,
+        user      => \@user_clauses,
+        status    => \@status_clauses,
+        queue     => \@queue_clauses,
+        owner     => \@owner_clauses,
+        other     => \@others_clauses,
+        final     => \@tql_clauses,
+    );
 
-        }
+    $self->ProcessAfterTranslate(
+        key_value => \@keyvalue_clauses,
+        number    => \@number_clauses,
+        user      => \@user_clauses,
+        status    => \@status_clauses,
+        queue     => \@queue_clauses,
+        owner     => \@owner_clauses,
+        other     => \@others_clauses,
+        final     => \@tql_clauses,
+    );
 
-        elsif ( $key =~ /\w+\@\w+/ ) {
-            push @user_clauses, "Requestor LIKE '$key'";
-        }
+    $self->CallbackAfterProcess(
+        key_value => \@keyvalue_clauses,
+        number    => \@number_clauses,
+        user      => \@user_clauses,
+        status    => \@status_clauses,
+        queue     => \@queue_clauses,
+        owner     => \@owner_clauses,
+        other     => \@others_clauses,
+        final     => \@tql_clauses,
+    );
 
-        # Is there a status with this name?
-        elsif (
-            $Queue = RT::Queue->new( $self->TicketsObj->CurrentUser )
-            and $Queue->IsValidStatus($key)
-          )
-        {
-            push @status_clauses, "Status = '" . $key . "'";
-        }
+    push @tql_clauses, join( " AND ", sort @keyvalue_clauses );    # Yes, AND!
 
-        # Is there a queue named $key?
-        elsif ( $Queue = RT::Queue->new( $self->TicketsObj->CurrentUser )
-            and $Queue->Load($key) )
-        {
-            my $quoted_queue = $Queue->Name;
-            $quoted_queue =~ s/'/\\'/g;
-            push @queue_clauses, "Queue = '$quoted_queue'";
-        }
+    push @tql_clauses, join( " OR ", sort @number_clauses );
+    push @tql_clauses, join( " OR ", sort @owner_clauses );
+    push @tql_clauses, join( " OR ", sort @user_clauses );
+    push @tql_clauses, join( " OR ", sort @queue_clauses );
+    push @tql_clauses, join( " OR ", sort @status_clauses );
+    push @tql_clauses, join( " OR ", sort @others_clauses );
+    @tql_clauses = grep { $_ ? $_ = "( $_ )" : undef } @tql_clauses;
+    return join " AND ", sort @tql_clauses;
+}
 
-        # Is there a owner named $key?
-        elsif ( $User = RT::User->new( $self->TicketsObj->CurrentUser )
-            and $User->Load($key)
-            and $User->Privileged )
-        {
-            push @owner_clauses, "Owner = '" . $User->Name . "'";
-        }
+# }}}
+
+# {{{ sub Prepare
+sub Prepare {
+    my $self = shift;
+    my $tql  = $self->QueryToSQL( $self->Argument );
+
+    $RT::Logger->debug($tql);
+
+    $self->TicketsObj->FromSQL($tql);
+    return (1);
+}
+
+# }}}
 
-        # Else, subject must contain $key
+sub TranslateKeyValue {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    if ( $key =~
+/(subject|cf\.(?:[^:]*?)|content|requestor|id|status|owner|queue|fulltext):(['"])?(.+)\2?/i
+      )
+    {
+        my $field = $1;
+        my $value = $3;
+
+        if ( $field =~ /id|status|owner|queue/i ) {
+            push @clauses, "$field = '$value'";
+        }
+        elsif ( $field =~ /fulltext/i ) {
+            push @clauses, "Content LIKE '$value'";
+        }
         else {
-            $key =~ s/['\\].*//g;
-            push @tql_clauses, "Subject LIKE '$key'";
+            push @clauses, "$field LIKE '$value'";
         }
     }
+    return @clauses;
+}
+
+sub TranslateNumber {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    if ( $key =~ /^\d+$/ ) {
+        push @clauses, "id = '$key'", "Subject LIKE '$key'";
+    }
+    return @clauses;
+}
+
+sub TranslateStatus {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    my $Queue = RT::Queue->new( $self->TicketsObj->CurrentUser );
+    if ( $Queue->IsValidStatus($key) ) {
+        push @clauses, "Status = '$key'";
+    }
+    return @clauses;
+}
+
+sub TranslateQueue {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    my $Queue = RT::Queue->new( $self->TicketsObj->CurrentUser );
+    $Queue->Load($key);
+    if ( $Queue->Id ) {
+        my $quoted_queue = $Queue->Name;
+        $quoted_queue =~ s/'/\\'/g;
+        push @clauses, "Queue = '$quoted_queue'";
+    }
+    return @clauses;
+}
+
+sub TranslateUser {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    if ( $key =~ /\w+\@\w+/ ) {
+        push @clauses, "Requestor LIKE '$key'";
+    }
+    return @clauses;
+}
+
+sub TranslateOwner {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    my $User = RT::User->new( $self->TicketsObj->CurrentUser );
+    if ( $User->Load($key) && $User->Privileged ) {
+        push @clauses, "Owner = '" . $User->Name . "'";
+    }
+    return @clauses;
+}
+
+sub TranslateOthers {
+    my $self = shift;
+    my $key  = shift;
+    my @clauses;
+    $key =~ s{^(['"])(.*)\1$}{$2};    # 'foo' => foo
+
+    $key =~ s/['\\].*//g;             # XXX what's the usage of this?
+    push @clauses, "Subject LIKE '$key'";
+    return @clauses;
+}
+
+sub ProcessAfterTranslate {
+    my $self           = shift;
+    my %args           = @_;
+    my $queue_clauses  = $args{queue};
+    my $status_clauses = $args{status};
 
     # restrict to any queues requested by the caller
-    for my $queue (@{ $self->{'Queues'} }) {
-        my $QueueObj = RT::Queue->new($self->TicketsObj->CurrentUser);
+    for my $queue ( @{ $self->{'Queues'} } ) {
+        my $QueueObj = RT::Queue->new( $self->TicketsObj->CurrentUser );
         $QueueObj->Load($queue) or next;
         my $quoted_queue = $QueueObj->Name;
         $quoted_queue =~ s/'/\\'/g;
-        push @queue_clauses, "Queue = '$quoted_queue'";
+        push @$queue_clauses, "Queue = '$quoted_queue'";
     }
 
-    push @tql_clauses, join( " OR ", sort @id_clauses );
-    push @tql_clauses, join( " OR ", sort @owner_clauses );
-    if ( ! @status_clauses ) {
-        push @tql_clauses, join( " OR ", map "Status = '$_'", RT::Queue->ActiveStatusArray());
-    } else {
-        push @tql_clauses, join( " OR ", sort @status_clauses );
+    if (
+        !@$status_clauses
+        && RT::Config->Get(
+            'OnlySearchActiveTicketsInSimpleSearch',
+            $self->TicketsObj->CurrentUser
+        )
+      )
+    {
+        push @$status_clauses,
+          join( " OR ", map "Status = '$_'", RT::Queue->ActiveStatusArray() );
     }
-    push @tql_clauses, join( " OR ", sort @user_clauses );
-    push @tql_clauses, join( " OR ", sort @queue_clauses );
-    @tql_clauses = grep { $_ ? $_ = "( $_ )" : undef } @tql_clauses;
-    return join " AND ", sort @tql_clauses;
 }
-# }}}
-
-# {{{ sub Prepare
-sub Prepare  {
-  my $self = shift;
-  my $tql = $self->QueryToSQL($self->Argument);
 
-  $RT::Logger->debug($tql);
+sub CallbackAfterProcess {
+    my $self = shift;
 
-  $self->TicketsObj->FromSQL($tql);
-  return(1);
 }
-# }}}
 
 eval "require RT::Search::Googleish_Vendor";
 die $@ if ($@ && $@ !~ qr{^Can't locate RT/Search/Googleish_Vendor.pm});
diff --git a/share/html/Search/Results.html b/share/html/Search/Results.html
index 3d12b69..633b506 100755
--- a/share/html/Search/Results.html
+++ b/share/html/Search/Results.html
@@ -177,6 +177,12 @@ my $genpage = sub {
         Page    => shift(@_),
     );
 };
+
+if ( RT->Config->Get('SearchResultsAutoRedirect') && $ticketcount == 1 ) {
+    RT::Interface::Web::Redirect( RT->Config->Get('WebURL')
+            ."Ticket/Display.html?id=". $session{tickets}->First->id );
+}
+
 my $BaseURL = RT->Config->Get('WebPath')."/Search/Results.html?";
 $link_rel{first} = $BaseURL . $genpage->(1)         if $Page > 1;
 $link_rel{prev}  = $BaseURL . $genpage->($Page - 1) if $Page > 1;

-----------------------------------------------------------------------


More information about the Rt-commit mailing list