* Work on firming up the plugin interface:
[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         hook(type => "checkconfig", id => "hyperestraier",
11                 call => \&checkconfig);
12         hook(type => "pagetemplate", id => "hyperestraier",
13                 call => \&pagetemplate);
14         hook(type => "delete", id => "hyperestraier",
15                 call => \&delete);
16         hook(type => "change", id => "hyperestraier",
17                 call => \&change);
18         hook(type => "cgi", id => "hyperestraier",
19                 call => \&cgi);
20 } # }}}
21
22 sub checkconfig () { #{{{
23         foreach my $required (qw(url cgiurl)) {
24                 if (! length $config{$required}) {
25                         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 = template("searchform.tmpl", blind_cache => 1);
40                         $searchform->param(searchaction => $config{cgiurl});
41                         $form=$searchform->output;
42                 }
43
44                 $template->param(searchform => $form);
45         }
46 } #}}}
47
48 sub delete (@) { #{{{
49         debug("cleaning hyperestraier search index");
50         estcmd("purge -cl");
51         estcfg();
52 } #}}}
53
54 sub change (@) { #{{{
55         debug("updating hyperestraier search index");
56         estcmd("gather -cm -bc -cl -sd",
57                 map {
58                         Encode::encode_utf8($config{destdir}."/".$renderedfiles{pagename($_)})
59                 } @_
60         );
61         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("$config{wikistatedir}/hyperestraier") || error("chdir: $!");
70                 exec("./".IkiWiki::basename($config{cgiurl})) || error("estseek.cgi failed");
71         }
72 } #}}}
73
74 my $configured=0;
75 sub estcfg () { #{{{
76         return if $configured;
77         $configured=1;
78         
79         my $estdir="$config{wikistatedir}/hyperestraier";
80         my $cgi=IkiWiki::basename($config{cgiurl});
81         $cgi=~s/\..*$//;
82         open(TEMPLATE, ">$estdir/$cgi.tmpl") ||
83                 error("write $estdir/$cgi.tmpl: $!");
84         print TEMPLATE IkiWiki::misctemplate("search", 
85                 "<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n");
86         close TEMPLATE;
87         open(TEMPLATE, ">$estdir/$cgi.conf") ||
88                 error("write $estdir/$cgi.conf: $!");
89         my $template=template("estseek.conf");
90         eval q{use Cwd 'abs_path'};
91         $template->param(
92                 index => $estdir,
93                 tmplfile => "$estdir/$cgi.tmpl",
94                 destdir => IkiWiki::abs_path($config{destdir}),
95                 url => $config{url},
96         );
97         print TEMPLATE $template->output;
98         close TEMPLATE;
99         $cgi="$estdir/".IkiWiki::basename($config{cgiurl});
100         unlink($cgi);
101         symlink("/usr/lib/estraier/estseek.cgi", $cgi) ||
102                 error("symlink $cgi: $!");
103 } # }}}
104
105 sub estcmd ($;@) { #{{{
106         my @params=split(' ', shift);
107         push @params, "-cl", "$config{wikistatedir}/hyperestraier";
108         if (@_) {
109                 push @params, "-";
110         }
111         
112         my $pid=open(CHILD, "|-");
113         if ($pid) {
114                 # parent
115                 foreach (@_) {
116                         print CHILD "$_\n";
117                 }
118                 close(CHILD) || error("estcmd @params exited nonzero: $?");
119         }
120         else {
121                 # child
122                 open(STDOUT, "/dev/null"); # shut it up (closing won't work)
123                 exec("estcmd", @params) || error("can't run estcmd");
124         }
125 } #}}}
126
127 1