lib/TWiki/UI/Search.pm
author Colas Nahaboo <colas@nahaboo.net>
Sat, 26 Jan 2008 15:50:53 +0100
changeset 0 414e01d06fd5
permissions -rw-r--r--
RELEASE 4.2.0 freetown
colas@0
     1
# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
colas@0
     2
#
colas@0
     3
# Copyright (C) 1999-2007 Peter Thoeny, peter@thoeny.org
colas@0
     4
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
colas@0
     5
# are listed in the AUTHORS file in the root of this distribution.
colas@0
     6
# NOTE: Please extend that file, not this notice.
colas@0
     7
#
colas@0
     8
# This program is free software; you can redistribute it and/or
colas@0
     9
# modify it under the terms of the GNU General Public License
colas@0
    10
# as published by the Free Software Foundation; either version 2
colas@0
    11
# of the License, or (at your option) any later version. For
colas@0
    12
# more details read LICENSE in the root of this distribution.
colas@0
    13
#
colas@0
    14
# This program is distributed in the hope that it will be useful,
colas@0
    15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
colas@0
    16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
colas@0
    17
#
colas@0
    18
# As per the GPL, removal of this notice is prohibited.
colas@0
    19
colas@0
    20
=begin twiki
colas@0
    21
colas@0
    22
---+ package TWiki::UI::Search
colas@0
    23
colas@0
    24
UI functions for searching.
colas@0
    25
colas@0
    26
=cut
colas@0
    27
colas@0
    28
package TWiki::UI::Search;
colas@0
    29
colas@0
    30
use strict;
colas@0
    31
colas@0
    32
require TWiki;
colas@0
    33
colas@0
    34
=pod
colas@0
    35
colas@0
    36
---++ StaticMethod search( $session )
colas@0
    37
colas@0
    38
Perform a search as dictated by CGI parameters:
colas@0
    39
colas@0
    40
| *Parameter:* | *Description:* | *Default:* |
colas@0
    41
| ="text"= | Search term. Is a keyword search, literal search or regular expression search, depending on the =type= parameter. SearchHelp has more | required |
colas@0
    42
| =search="text"= | (Alternative to above) | N/A |
colas@0
    43
| =web="Name"= <br /> =web="%USERSWEB%, 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 |
colas@0
    44
| =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 |
colas@0
    45
| =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 |
colas@0
    46
| =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%) |
colas@0
    47
| =scope="topic"= <br /> =scope="text"= <br /> =scope="all"= | Search topic name (title); the text (body) of topic; or all (both) | ="text"= |
colas@0
    48
| =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 |
colas@0
    49
| =limit="all"= <br /> =limit="16"= | Limit the number of results returned. This is done after sorting if =order= is specified | All results |
colas@0
    50
| =date="..."= | limits the results to those pages with latest edit time in the given TimeInterval.  | All results |
colas@0
    51
| =reverse="on"= | Reverse the direction of the search | Ascending search |
colas@0
    52
| =casesensitive="on"= | Case sensitive search | Ignore case |
colas@0
    53
| =bookview="on"= | BookView search, e.g. show complete topic text | Show topic summary |
colas@0
    54
| =nonoise="on"= | Shorthand for =nosummary="on" nosearch="on" nototal="on" zeroresults="off" noheader="on" noempty="on"= | Off |
colas@0
    55
| =nosummary="on"= | Show topic title only | Show topic summary |
colas@0
    56
| =nosearch="on"= | Suppress search string | Show search string |
colas@0
    57
| =noheader="on"= | Suppress search header <br /> <span style='background: #FFB0B0;'> *Topics: Changed: By:* </span> | Show search header |
colas@0
    58
| =nototal="on"= | Do not show number of topics found | Show number |
colas@0
    59
| =zeroresults="off"= | Suppress all output if there are no hits | =zeroresults="on"=, displays: "Number of topics: 0" |
colas@0
    60
| =noempty="on"= | Suppress results for webs that have no hits. | Show webs with no hits |
colas@0
    61
| =header="..."= <br /> =format="..."= | Custom format results: see *[[FormattedSearch]]* for usage, variables &amp; examples | Results in table |
colas@0
    62
| =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 |
colas@0
    63
| =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 |
colas@0
    64
| =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= |
colas@0
    65
| =separator=", "= | Line separator between hits | Newline ="$n"= |
colas@0
    66
colas@0
    67
=cut
colas@0
    68
colas@0
    69
sub search {
colas@0
    70
    my $session = shift;
colas@0
    71
colas@0
    72
    my $query = $session->{cgiQuery};
colas@0
    73
    my $webName = $session->{webName};
colas@0
    74
    my $topic = $session->{topicName};
colas@0
    75
colas@0
    76
    unless ( $session->{store}->webExists( $webName ) ) {
colas@0
    77
        require TWiki::OopsException;
colas@0
    78
        throw TWiki::OopsException(
colas@0
    79
            'accessdenied',
colas@0
    80
            def => 'no_such_web',
colas@0
    81
            web => $webName,
colas@0
    82
            topic => $topic,
colas@0
    83
            params => [ 'search' ] );
colas@0
    84
    }
colas@0
    85
colas@0
    86
    # The CGI.pm docs claim that it returns all of the values in a
colas@0
    87
    # multiple select if called in a list context, but that may not
colas@0
    88
    # work (didn't on the dev box -- perl 5.004_4 and CGI.pm 2.36 on
colas@0
    89
    # Linux (Slackware 2.0.33) with Apache 1.2.  That being the case,
colas@0
    90
    # we need to parse them out here.
colas@0
    91
colas@0
    92
#    my @webs          = $query->param( 'web' ) || ( $webName ); #doesn't work
colas@0
    93
colas@0
    94
    # Note for those unused to Perlishness:
colas@0
    95
    # -------------------------------------
colas@0
    96
    # The pipeline at the end of this assignment splits the full query
colas@0
    97
    # string on '&' or ';' and selects out the params that begin with 'web=',
colas@0
    98
    # replacing them with whatever is after that.  In the case of a
colas@0
    99
    # single list of webs passed as a string (say, from a text entry
colas@0
   100
    # field) it does more processing than it needs to to get the
colas@0
   101
    # correct string, but so what?  The pipline is the second
colas@0
   102
    # parameter to the join, and consists of the last two lines.  The
colas@0
   103
    # join takes the results of the pipeline and strings them back
colas@0
   104
    # together, space delimited, which is exactly what &searchWeb
colas@0
   105
    # needs.
colas@0
   106
    # Note that mod_perl/cgi appears to use ';' as separator, whereas plain cgi uses '&'
colas@0
   107
colas@0
   108
    my $attrWeb       = join ' ',
colas@0
   109
                        grep { s/^web=(.*)$/$1/ }
colas@0
   110
                        split(/[&;]/, $query->query_string);
colas@0
   111
    # need to unescape URL-encoded data since we use the raw query_string
colas@0
   112
    # suggested by JeromeBouvattier
colas@0
   113
    $attrWeb =~ tr/+/ /;       # pluses become spaces
colas@0
   114
    $attrWeb =~ s/%([0-9a-fA-F]{2})/pack('c',hex($1))/ge;  # %20 becomes space
colas@0
   115
colas@0
   116
    # 'scalar' is used below to get the scalar value of the parameter
colas@0
   117
    # because it returns the empty string for undef.
colas@0
   118
colas@0
   119
    my $text = $session->search->searchWeb(
colas@0
   120
#        _callback       => \&_contentCallback,	#FIXME - can't process format=| $topic | line by line...
colas@0
   121
        _callback       => undef,
colas@0
   122
        _cbdata         => undef,
colas@0
   123
        'inline'          => 0,
colas@0
   124
        'search'        => scalar $query->param( 'search' ),
colas@0
   125
        'web'           => $attrWeb,
colas@0
   126
        'topic'         => scalar $query->param( 'topic' ),
colas@0
   127
        'excludetopic'  => scalar $query->param( 'excludetopic' ),
colas@0
   128
        'scope'         => scalar $query->param( 'scope' ),
colas@0
   129
        'order'         => scalar $query->param( 'order' ),
colas@0
   130
        'type'          => scalar $query->param( 'type' ) ||
colas@0
   131
          $session->{prefs}->getPreferencesValue( 'SEARCHDEFAULTTTYPE' ),
colas@0
   132
        'regex'         => scalar $query->param( 'regex' ),
colas@0
   133
        'limit'         => scalar $query->param( 'limit' ),
colas@0
   134
        'reverse'       => scalar $query->param( 'reverse' ),
colas@0
   135
        'casesensitive' => scalar $query->param( 'casesensitive' ),
colas@0
   136
        'nosummary'     => scalar $query->param( 'nosummary' ),
colas@0
   137
        'nosearch'      => scalar $query->param( 'nosearch' ),
colas@0
   138
        'noheader'      => scalar $query->param( 'noheader' ),
colas@0
   139
        'nototal'       => scalar $query->param( 'nototal' ),
colas@0
   140
        'bookview'      => scalar $query->param( 'bookview' ),
colas@0
   141
        'showlock'      => scalar $query->param( 'showlock' ),
colas@0
   142
        'expandvariables' => scalar $query->param( 'expandvariables' ),
colas@0
   143
        'noempty'       => scalar $query->param( 'noempty' ),
colas@0
   144
        'template'      => scalar $query->param( 'template' ),
colas@0
   145
        'header'        => scalar $query->param( 'header' ),
colas@0
   146
        'format'        => scalar $query->param( 'format' ),
colas@0
   147
        'multiple'      => scalar $query->param( 'multiple' ),
colas@0
   148
        'separator'     => scalar $query->param( 'separator' ),
colas@0
   149
        'subweb'     => scalar $query->param( 'subweb' )
colas@0
   150
    );
colas@0
   151
 
colas@0
   152
    $session->writeCompletePage($text);
colas@0
   153
    
colas@0
   154
}
colas@0
   155
colas@0
   156
sub _contentCallback {
colas@0
   157
    TWiki::spamProof( $_[1] );
colas@0
   158
#FIXME: if you're going to define a callback, you have to convert from TML too    
colas@0
   159
    print $_[1];
colas@0
   160
}
colas@0
   161
colas@0
   162
1;
colas@0
   163