%# BEGIN LICENSE BLOCK %# %# Copyright (c) 2002-2003 Jesse Vincent %# %# This program is free software; you can redistribute it and/or modify %# it under the terms of version 2 of the GNU General Public License %# as published by the Free Software Foundation. %# %# A copy of that license should have arrived with this %# software, but in any event can be snarfed from www.gnu.org. %# %# This program 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. %# %# END LICENSE BLOCK <& /RTFM/Article/Elements/Tabs, current_tab => "RTFM/Article/Search.html", Title => loc("Search for articles") &> <& Elements/ShowSearchResults, articles => $articles &> <& Elements/ShowSearchCriteria, dates => \%dates, RefersTo => $RefersTo, customfields => $customfields, ReferredToBy => $ReferredToBy, %ARGS &> <%init> my @results; my $articles = RT::FM::ArticleCollection->new( $session{'CurrentUser'} ); my $customfields = RT::FM::CustomFieldCollection->new( $session{'CurrentUser'} ); if ( $ARGS{'Class'} ) { my @Classes = ( ref $ARGS{'Class'} eq 'ARRAY' ) ? @{ $ARGS{'Class'} } : ( $ARGS{'Class'} ); foreach my $class (@Classes) { $customfields->LimitToClass($class); } } else { $customfields->UnLimit(); } # Don't want to search for a null class when there is no class specced my %dates; foreach my $date qw(Created< Created> LastUpdated< LastUpdated>) { next unless ( $ARGS{$date} ); my $seconds = parsedate( $ARGS{$date}, FUZZY => 1, PREFER_PAST => 1 ); my $date_obj = RT::Date->new( $session{'CurrentUser'} ); $date_obj->Set( Format => 'unix', Value => $seconds ); $dates{$date} = $date_obj; if ( $date =~ /^(.*?)<$/i ) { $articles->Limit( FIELD => $1, OPERATOR => "<=", ENTRYAGGREGATOR => "AND", VALUE => $date_obj->ISO ); } if ( $date =~ /^(.*?)>$/i ) { $articles->Limit( FIELD => $1, OPERATOR => ">=", ENTRYAGGREGATOR => "AND", VALUE => $date_obj->ISO ); } } foreach my $link ( split ( /\s+/, $RefersTo ) ) { next unless ($link); $articles->LimitRefersTo($link); } foreach my $link ( split ( /\s+/, $ReferredToBy ) ) { next unless ($link); $articles->LimitReferredToBy($link); } my %cfs; my $all_cfs = RT::FM::CustomFieldCollection->new($session{'CurrentUser'}); $all_cfs->UnLimit(); while ( my $cf = $all_cfs->Next ) { $cfs{ $cf->Name } = $cf->Id; } foreach my $field ( keys %cfs ) { my @MatchLike = (ref $ARGS{ $field."~" } eq 'ARRAY' ) ? @{ $ARGS{ $field."~" } } : ( $ARGS{$field."~" } ); my @NoMatchLike = (ref $ARGS{ $field."!~" } eq 'ARRAY' ) ? @{ $ARGS{ $field."!~" } } : ( $ARGS{$field."!~" } ); my @Match = (ref $ARGS{ $field } eq 'ARRAY' ) ? @{ $ARGS{ $field } } : ( $ARGS{$field } ); my @NoMatch = (ref $ARGS{ $field."!" } eq 'ARRAY' ) ? @{ $ARGS{ $field."!" } } : ( $ARGS{$field."!" } ); foreach my $val (@MatchLike) { next unless $val; push @Match, "~".$val; } foreach my $val (@NoMatchLike) { next unless $val; push @NoMatch, "~".$val; } foreach my $value (@Match) { next unless $value; my $op; if ( $value =~ /^~(.*)$/ ) { $value = "%$1%"; $op = 'LIKE'; } else { $op = '='; } $articles->LimitCustomField( FIELD => $cfs{$field}, VALUE => $value, ENTRYAGGREGATOR => 'OR', OPERATOR => $op ); } foreach my $value (@NoMatch) { next unless $value; my $op; if ( $value =~ /^~(.*)$/ ) { $value = "%$1%"; $op = 'NOT LIKE'; } else { $op = '!='; } $articles->LimitCustomField( FIELD => $cfs{$field}, VALUE => $value, ENTRYAGGREGATOR => 'OR', OPERATOR => $op ); } } foreach my $field qw(Name Summary Class) { my @MatchLike = (ref $ARGS{ $field."~" } eq 'ARRAY' ) ? @{ $ARGS{ $field."~" } } : ( $ARGS{$field."~" } ); my @NoMatchLike = (ref $ARGS{ $field."!~" } eq 'ARRAY' ) ? @{ $ARGS{ $field."!~" } } : ( $ARGS{$field."!~" } ); my @Match = (ref $ARGS{ $field } eq 'ARRAY' ) ? @{ $ARGS{ $field } } : ( $ARGS{$field } ); my @NoMatch = (ref $ARGS{ $field."!" } eq 'ARRAY' ) ? @{ $ARGS{ $field."!" } } : ( $ARGS{$field."!" } ); foreach my $val (@MatchLike) { next unless $val; push @Match, "~".$val; } foreach my $val (@NoMatchLike) { next unless $val; push @NoMatch, "~".$val; } my $op; foreach my $value (@Match) { if ( $value =~ /^~(.*)$/ ) { $value = "%$1%"; $op = 'LIKE'; } else { $op = '='; } # preprocess Classes, so we can search on class if ( $field eq 'Class' ) { $RT::Logger->crit("Checking for a class of $value"); my $class = RT::FM::Class->new($RT::SystemUser); $class->Load($value); $value = $class->Id; } # now that we've pruned the value, get out if it's different. next unless $value; $articles->Limit( SUBCLAUSE => $field . 'Match', FIELD => $field, OPERATOR => $op, VALUE => $value, ENTRYAGGREGATOR => 'OR' ); } foreach my $value (@NoMatch) { $RT::Logger->debug( "noMatch value is '$value' for $field"); # preprocess Classes, so we can search on class if ( $value =~ /^~(.*)/ ) { $value = "%$1%"; $op = 'NOT LIKE'; } else { $op = '!='; } if ( $field eq 'Class' ) { my $class = RT::FM::Class->new($RT::SystemUser); $class->Load($value); $value = $class->Id; } # now that we've pruned the value, get out if it's different. next unless $value; $articles->Limit( SUBCLAUSE => $field . 'NoMatch', OPERATOR => $op, VALUE => $value, FIELD => $field, ENTRYAGGREGATOR => 'AND' ); } } <%ARGS> $CreatedBefore => '' $CreatedAfter => '' $LastUpdatedBefore => '' $LastUpdatedAfter => '' $RefersTo => undef $ReferredToBy => undef