* Support inlining pages raw, rather than creating a blog.
[ikiwiki] / 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 sub pagetemplate (@) { #{{{
31         my %params=@_;
32         my $page=$params{page};
33         my $template=$params{template};
34
35         # Add search box to page header.
36         if ($template->query(name => "searchform")) {
37                 $template->param(searchform => qq{
38 <form method="get" action="$IkiWiki::config{cgiurl}" id="searchform">
39 <div>
40 <input type="text" name="phrase" value="" size="16" />
41 <input type="hidden" name="enc" value="UTF-8" />
42 <input type="hidden" name="do" value="hyperestraier" />
43 </div>
44 </form>
45 });
46         }
47 } #}}}
48
49 sub delete (@) { #{{{
50         IkiWiki::debug("cleaning hyperestraier search index");
51         IkiWiki::estcmd("purge -cl");
52         IkiWiki::estcfg();
53 } #}}}
54
55 sub change (@) { #{{{
56         IkiWiki::debug("updating hyperestraier search index");
57         IkiWiki::estcmd("gather -cm -bc -cl -sd",
58                 map {
59                         Encode::encode_utf8($IkiWiki::config{destdir}."/".$IkiWiki::renderedfiles{IkiWiki::pagename($_)})
60                 } @_
61         );
62         IkiWiki::estcfg();
63 } #}}}
64
65 sub cgi ($) { #{{{
66         my $cgi=shift;
67
68         if (defined $cgi->param('phrase')) {
69                 # only works for GET requests
70                 chdir("$IkiWiki::config{wikistatedir}/hyperestraier") || IkiWiki::error("chdir: $!");
71                 exec("./".IkiWiki::basename($IkiWiki::config{cgiurl})) || IkiWiki::error("estseek.cgi failed");
72         }
73 } #}}}
74
75 # Easier to keep these in the IkiWiki namespace.
76 package IkiWiki;
77
78 my $configured=0;
79 sub estcfg () { #{{{
80         return if $configured;
81         $configured=1;
82         
83         my $estdir="$config{wikistatedir}/hyperestraier";
84         my $cgi=basename($config{cgiurl});
85         $cgi=~s/\..*$//;
86         open(TEMPLATE, ">$estdir/$cgi.tmpl") ||
87                 error("write $estdir/$cgi.tmpl: $!");
88         print TEMPLATE misctemplate("search", 
89                 "<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n");
90         close TEMPLATE;
91         open(TEMPLATE, ">$estdir/$cgi.conf") ||
92                 error("write $estdir/$cgi.conf: $!");
93         my $template=template("estseek.conf");
94         eval q{use Cwd 'abs_path'};
95         $template->param(
96                 index => $estdir,
97                 tmplfile => "$estdir/$cgi.tmpl",
98                 destdir => abs_path($config{destdir}),
99                 url => $config{url},
100         );
101         print TEMPLATE $template->output;
102         close TEMPLATE;
103         $cgi="$estdir/".basename($config{cgiurl});
104         unlink($cgi);
105         symlink("/usr/lib/estraier/estseek.cgi", $cgi) ||
106                 error("symlink $cgi: $!");
107 } # }}}
108
109 sub estcmd ($;@) { #{{{
110         my @params=split(' ', shift);
111         push @params, "-cl", "$config{wikistatedir}/hyperestraier";
112         if (@_) {
113                 push @params, "-";
114         }
115         
116         my $pid=open(CHILD, "|-");
117         if ($pid) {
118                 # parent
119                 foreach (@_) {
120                         print CHILD "$_\n";
121                 }
122                 close(CHILD) || error("estcmd @params exited nonzero: $?");
123         }
124         else {
125                 # child
126                 open(STDOUT, "/dev/null"); # shut it up (closing won't work)
127                 exec("estcmd", @params) || error("can't run estcmd");
128         }
129 } #}}}
130
131 1