wiki-archive/twiki/lib/TWiki/UI/Search.pm

156 lines
8.9 KiB
Perl

# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
#
# Copyright (C) 1999-2007 Peter Thoeny, peter@thoeny.org
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. For
# more details read LICENSE in the root of this distribution.
#
# 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.
#
# As per the GPL, removal of this notice is prohibited.
=begin twiki
---+ package TWiki::UI::Search
UI functions for searching.
=cut
package TWiki::UI::Search;
use strict;
use TWiki;
use TWiki::UI;
=pod
---++ StaticMethod search( $session )
Perform a search as dictated by CGI parameters:
| *Parameter:* | *Description:* | *Default:* |
| ="text"= | Search term. Is a keyword search, literal search or regular expression search, depending on the =type= parameter. SearchHelp has more | required |
| =search="text"= | (Alternative to above) | N/A |
| =web="Name"= <br /> =web="%MAINWEB%, Know"= <br /> =web="all"= | Comma-separated list of webs to search. The special word =all= means all webs that doe *not* have the =NOSEARCHALL= variable set to =on= in their %WEBPREFSTOPIC%. You can specifically *exclude* webs from an =all= search using a minus sign - for example, =web="all,-Secretweb"=. | Current web |
| =topic="%WEBPREFSTOPIC%"= <br /> =topic="*Bug"= | Limit search to topics: A topic, a topic with asterisk wildcards, or a list of topics separated by comma. | All topics in a web |
| =excludetopic="Web*"= <br /> =excludetopic="%HOMETOPIC%, <nop>WebChanges"= | Exclude topics from search: A topic, a topic with asterisk wildcards, or a list of topics separated by comma. | None |
| =type="keyword"= <br /> =type="literal"= <br /> =type="regex"= | Do a keyword search like =soap "web service" -shampoo=; a literal search like =web service=; or RegularExpression search like =soap;web service;!shampoo= | =%<nop>SEARCHVAR- DEFAULTTYPE%= [[TWikiPreferences][preferences]] setting (%SEARCHVARDEFAULTTYPE%) |
| =scope="topic"= <br /> =scope="text"= <br /> =scope="all"= | Search topic name (title); the text (body) of topic; or all (both) | ="text"= |
| =order="topic"= <br /> =order="created"= <br /> =order="modified"= <br /> =order="editby"= <br /> =order=<br />&nbsp;"formfield(name)"= | Sort the results of search by the topic names, topic creation time, last modified time, last editor, or named field of TWikiForms. The sorting is done web by web; in case you want to sort across webs, create a [[FormattedSearch][formatted]] table and sort it with TablePlugin's initsort | Sort by topic name |
| =limit="all"= <br /> =limit="16"= | Limit the number of results returned. This is done after sorting if =order= is specified | All results |
| =date="..."= | limits the results to those pages with latest edit time in the given TimeInterval. | All results |
| =reverse="on"= | Reverse the direction of the search | Ascending search |
| =casesensitive="on"= | Case sensitive search | Ignore case |
| =bookview="on"= | BookView search, e.g. show complete topic text | Show topic summary |
| =nonoise="on"= | Shorthand for =nosummary="on" nosearch="on" nototal="on" zeroresults="off" noheader="on" noempty="on"= | Off |
| =nosummary="on"= | Show topic title only | Show topic summary |
| =nosearch="on"= | Suppress search string | Show search string |
| =noheader="on"= | Suppress search header <br /> <span style='background: #FFB0B0;'> *Topics: Changed: By:* </span> | Show search header |
| =nototal="on"= | Do not show number of topics found | Show number |
| =zeroresults="off"= | Suppress all output if there are no hits | =zeroresults="on"=, displays: "Number of topics: 0" |
| =noempty="on"= | Suppress results for webs that have no hits. | Show webs with no hits |
| =header="..."= <br /> =format="..."= | Custom format results: see *[[FormattedSearch]]* for usage, variables &amp; examples | Results in table |
| =expandvariables="on"= | Expand variables before applying a FormattedSearch on a search hit. Useful to show the expanded text, e.g. to show the result of a SpreadSheetPlugin =%<nop>CALC{}%= instead of the formula | Raw text |
| =multiple="on"= | Multiple hits per topic. Each hit can be [[FormattedSearch][formatted]]. The last token is used in case of a regular expression ";" _and_ search | Only one hit per topic |
| =nofinalnewline="on"= | If =on=, the search variable does not end in a line by itself. Any text continuing immediately after the search tag on the same line will be rendered as part of the table generated by the search, if appropriate. | =off= |
| =separator=", "= | Line separator between hits | Newline ="$n"= |
=cut
sub search {
my $session = shift;
my $query = $session->{cgiQuery};
my $webName = $session->{webName};
my $topic = $session->{topicName};
TWiki::UI::checkWebExists( $session, $webName, $topic, 'search' );
# The CGI.pm docs claim that it returns all of the values in a
# multiple select if called in a list context, but that may not
# work (didn't on the dev box -- perl 5.004_4 and CGI.pm 2.36 on
# Linux (Slackware 2.0.33) with Apache 1.2. That being the case,
# we need to parse them out here.
# my @webs = $query->param( 'web' ) || ( $webName ); #doesn't work
# Note for those unused to Perlishness:
# -------------------------------------
# The pipeline at the end of this assignment splits the full query
# string on '&' or ';' and selects out the params that begin with 'web=',
# replacing them with whatever is after that. In the case of a
# single list of webs passed as a string (say, from a text entry
# field) it does more processing than it needs to to get the
# correct string, but so what? The pipline is the second
# parameter to the join, and consists of the last two lines. The
# join takes the results of the pipeline and strings them back
# together, space delimited, which is exactly what &searchWeb
# needs.
# Note that mod_perl/cgi appears to use ';' as separator, whereas plain cgi uses '&'
my $attrWeb = join ' ',
grep { s/^web=(.*)$/$1/ }
split(/[&;]/, $query->query_string);
# need to unescape URL-encoded data since we use the raw query_string
# suggested by JeromeBouvattier
$attrWeb =~ tr/+/ /; # pluses become spaces
$attrWeb =~ s/%([0-9a-fA-F]{2})/pack('c',hex($1))/ge; # %20 becomes space
# $session->writePageHeader();
# SMELL: what's all the 'scalar' crud, below?
my $text = $session->{search}->searchWeb(
# _callback => \&_contentCallback, #FIXME - can't process format=| $topic | line by line...
_callback => undef,
_cbdata => undef,
'inline' => 0,
'search' => scalar $query->param( 'search' ),
'web' => $attrWeb,
'topic' => scalar $query->param( 'topic' ),
'excludetopic' => scalar $query->param( 'excludetopic' ),
'scope' => scalar $query->param( 'scope' ),
'order' => scalar $query->param( 'order' ),
'type' => scalar $query->param( 'type' ) ||
$session->{prefs}->getPreferencesValue( 'SEARCHDEFAULTTTYPE' ),
'regex' => scalar $query->param( 'regex' ),
'limit' => scalar $query->param( 'limit' ),
'reverse' => scalar $query->param( 'reverse' ),
'casesensitive' => scalar $query->param( 'casesensitive' ),
'nosummary' => scalar $query->param( 'nosummary' ),
'nosearch' => scalar $query->param( 'nosearch' ),
'noheader' => scalar $query->param( 'noheader' ),
'nototal' => scalar $query->param( 'nototal' ),
'bookview' => scalar $query->param( 'bookview' ),
'showlock' => scalar $query->param( 'showlock' ),
'expandvariables' => scalar $query->param( 'expandvariables' ),
'noempty' => scalar $query->param( 'noempty' ),
'template' => scalar $query->param( 'template' ),
'header' => scalar $query->param( 'header' ),
'format' => scalar $query->param( 'format' ),
'multiple' => scalar $query->param( 'multiple' ),
'separator' => scalar $query->param( 'separator' ),
'subweb' => scalar $query->param( 'subweb' )
);
$session->writeCompletePage($text);
}
sub _contentCallback {
TWiki::spamProof( $_[1] );
#FIXME: if you're going to define a callback, you have to convert from TML too
print $_[1];
}
1;