c8e0dd580224a7dc810208c1ac3f294633b1f5ab
[ikiwiki.git] / IkiWiki / Plugin / search.pm
1 #!/usr/bin/perl
2 # hyperestraier search engine plugin
3 package IkiWiki::Plugin::search;
4
5 use warnings;
6 use strict;
7 use IkiWiki;
8
9 sub import { #{{{
10         IkiWiki::hook(type => "checkconfig", id => "hyperestraier",
11                 call => \&checkconfig);
12         IkiWiki::hook(type => "pagetemplate", id => "hyperestraier",
13                 call => \&pagetemplate);
14         IkiWiki::hook(type => "delete", id => "hyperestraier",
15                 call => \&delete);
16         IkiWiki::hook(type => "change", id => "hyperestraier",
17                 call => \&change);
18         IkiWiki::hook(type => "cgi", id => "hyperestraier",
19                 call => \&cgi);
20 } # }}}
21
22 sub checkconfig () { #{{{
23         foreach my $required (qw(url cgiurl)) {
24                 if (! length $IkiWiki::config{$required}) {
25                         IkiWiki::error("Must specify $required when using the search plugin\n");
26                 }
27         }
28 } #}}}
29
30 my $form;
31 sub pagetemplate (@) { #{{{
32         my %params=@_;
33         my $page=$params{page};
34         my $template=$params{template};
35
36         # Add search box to page header.
37         if ($template->query(name => "searchform")) {
38                 if (! defined $form) {
39                         my $searchform = IkiWiki::template("searchform.tmpl", blind_cache => 1);
40                         $searchform->param(searchaction => $IkiWiki::config{cgiurl});
41                         $form=$searchform->output;
42                 }
43
44                 $template->param(searchform => $form);
45         }
46 } #}}}
47
48 sub delete (@) { #{{{
49         IkiWiki::debug("cleaning hyperestraier search index");
50         IkiWiki::estcmd("purge -cl");
51         IkiWiki::estcfg();
52 } #}}}
53
54 sub change (@) { #{{{
55         IkiWiki::debug("updating hyperestraier search index");
56         IkiWiki::estcmd("gather -cm -bc -cl -sd",
57                 map {
58                         Encode::encode_utf8($IkiWiki::config{destdir}."/".$IkiWiki::renderedfiles{IkiWiki::pagename($_)})
59                 } @_
60         );
61         IkiWiki::estcfg();
62 } #}}}
63
64 sub cgi ($) { #{{{
65         my $cgi=shift;
66
67         if (defined $cgi->param('phrase')) {
68                 # only works for GET requests
69                 chdir("$IkiWiki::config{wikistatedir}/hyperestraier") || IkiWiki::error("chdir: $!");
70                 exec("./".IkiWiki::basename($IkiWiki::config{cgiurl})) || IkiWiki::error("estseek.cgi failed");
71         }
72 } #}}}
73
74 # Easier to keep these in the IkiWiki namespace.
75 package IkiWiki;
76
77 my $configured=0;
78 sub estcfg () { #{{{
79         return if $configured;
80         $configured=1;
81         
82         my $estdir="$config{wikistatedir}/hyperestraier";
83         my $cgi=basename($config{cgiurl});
84         $cgi=~s/\..*$//;
85         open(TEMPLATE, ">$estdir/$cgi.tmpl") ||
86                 error("write $estdir/$cgi.tmpl: $!");
87         print TEMPLATE misctemplate("search", 
88                 "<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n");
89         close TEMPLATE;
90         open(TEMPLATE, ">$estdir/$cgi.conf") ||
91                 error("write $estdir/$cgi.conf: $!");
92         my $template=template("estseek.conf");
93         eval q{use Cwd 'abs_path'};
94         $template->param(
95                 index => $estdir,
96                 tmplfile => "$estdir/$cgi.tmpl",
97                 destdir => abs_path($config{destdir}),
98                 url => $config{url},
99         );
100         print TEMPLATE $template->output;
101         close TEMPLATE;
102         $cgi="$estdir/".basename($config{cgiurl});
103         unlink($cgi);
104         symlink("/usr/lib/estraier/estseek.cgi", $cgi) ||
105                 error("symlink $cgi: $!");
106 } # }}}
107
108 sub estcmd ($;@) { #{{{
109         my @params=split(' ', shift);
110         push @params, "-cl", "$config{wikistatedir}/hyperestraier";
111         if (@_) {
112                 push @params, "-";
113         }
114         
115         my $pid=open(CHILD, "|-");
116         if ($pid) {
117                 # parent
118                 foreach (@_) {
119                         print CHILD "$_\n";
120                 }
121                 close(CHILD) || error("estcmd @params exited nonzero: $?");
122         }
123         else {
124                 # child
125                 open(STDOUT, "/dev/null"); # shut it up (closing won't work)
126                 exec("estcmd", @params) || error("can't run estcmd");
127         }
128 } #}}}
129
130 1