rather a lot of changes to make hyperestraier search be a plugin, allowing

for other types of search engine plugins if wanted, and also opening up a
lot of new possibilities for other kinds of plugins later

some notable changes along the way:

- lots of new hook types: cgi, render, delete
- wrapper files fixed to support config strings with newlines in them
- HEADERCONTENT in page template useful for plugins. Probably needs to be
  expanded to more such for other places plugins might want to add content.
- remove unnecessary wrappers field from config info stored in wrappers
master
joey 2006-05-03 21:50:39 +00:00
parent b0952742b2
commit af9566ff1a
15 changed files with 204 additions and 106 deletions

View File

@ -16,9 +16,6 @@ sub checkconfig () { #{{{
if ($config{rss} && ! length $config{url}) { if ($config{rss} && ! length $config{url}) {
error("Must specify url to wiki with --url when using --rss\n"); error("Must specify url to wiki with --url when using --rss\n");
} }
if ($config{hyperestraier} && ! length $config{url}) {
error("Must specify --url when using --hyperestraier\n");
}
$config{wikistatedir}="$config{srcdir}/.ikiwiki" $config{wikistatedir}="$config{srcdir}/.ikiwiki"
unless exists $config{wikistatedir}; unless exists $config{wikistatedir};
@ -40,6 +37,12 @@ sub checkconfig () { #{{{
error("Failed to load plugin $mod: $@"); error("Failed to load plugin $mod: $@");
} }
} }
if (exists $hooks{checkconfig}) {
foreach my $id (keys %{$hooks{checkconfig}}) {
$hooks{checkconfig}{$id}{call}->();
}
}
} #}}} } #}}}
sub error ($) { #{{{ sub error ($) { #{{{

View File

@ -484,26 +484,21 @@ sub cgi_editpage ($$) { #{{{
} }
} #}}} } #}}}
sub cgi_hyperestraier () { #{{{
# only works for GET requests
chdir("$config{wikistatedir}/hyperestraier") || error("chdir: $!");
exec("./".basename($config{cgiurl})) || error("estseek.cgi failed");
} #}}}
sub cgi () { #{{{ sub cgi () { #{{{
eval q{use CGI}; eval q{use CGI};
eval q{use CGI::Session}; eval q{use CGI::Session};
my $q=CGI->new; my $q=CGI->new;
if (exists $hooks{cgi}) {
foreach my $id (keys %{$hooks{cgi}}) {
$hooks{cgi}{$id}{call}->($q);
}
}
my $do=$q->param('do'); my $do=$q->param('do');
if (! defined $do || ! length $do) { if (! defined $do || ! length $do) {
if (defined $q->param('phrase')) { error("\"do\" parameter missing");
cgi_hyperestraier();
}
else {
error("\"do\" parameter missing");
}
} }
# Things that do not need a session. # Things that do not need a session.

View File

@ -0,0 +1,122 @@
#!/usr/bin/perl
# hyperestraier search engine plugin
package IkiWiki::Plugin::search;
use warnings;
use strict;
use IkiWiki;
sub import { #{{{
IkiWiki::hook(type => "checkconfig", id => "hyperestraier",
call => \&checkconfig);
IkiWiki::hook(type => "delete", id => "hyperestraier",
call => \&delete);
IkiWiki::hook(type => "render", id => "hyperestraier",
call => \&render);
IkiWiki::hook(type => "cgi", id => "hyperestraier",
call => \&cgi);
} # }}}
sub checkconfig () { #{{{
foreach my $required (qw(url cgiurl)) {
if (! length $IkiWiki::config{$required}) {
IkiWiki::error("Must specify $required when using the search plugin\n");
}
}
$IkiWiki::config{headercontent}.=qq{
<form method="get" action="$IkiWiki::config{cgiurl}" id="searchform">
<div>
<input type="text" name="phrase" value="" size="16" />
<input type="hidden" name="enc" value="UTF-8" />
<input type="hidden" name="do" value="hyperestraier" />
</div>
</form>
};
} #}}}
sub delete (@) { #{{{
IkiWiki::debug("cleaning hyperestraier search index");
IkiWiki::estcmd("purge -cl");
IkiWiki::estcfg();
} #}}}
sub render (@) { #{{{
IkiWiki::debug("updating hyperestraier search index");
IkiWiki::estcmd("gather -cm -bc -cl -sd",
map {
$IkiWiki::config{destdir}."/".$IkiWiki::renderedfiles{IkiWiki::pagename($_)}
} @_
);
IkiWiki::estcfg();
} #}}}
sub cgi ($) { #{{{
my $cgi=shift;
if (defined $cgi->param('phrase')) {
# only works for GET requests
chdir("$IkiWiki::config{wikistatedir}/hyperestraier") || IkiWiki::error("chdir: $!");
exec("./".IkiWiki::basename($IkiWiki::config{cgiurl})) || IkiWiki::error("estseek.cgi failed");
}
} #}}}
# Easier to keep these in the IkiWiki namespace.
package IkiWiki;
my $configured=0;
sub estcfg () { #{{{
return if $configured;
$configured=1;
my $estdir="$config{wikistatedir}/hyperestraier";
my $cgi=basename($config{cgiurl});
$cgi=~s/\..*$//;
open(TEMPLATE, ">$estdir/$cgi.tmpl") ||
error("write $estdir/$cgi.tmpl: $!");
print TEMPLATE misctemplate("search",
"<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n");
close TEMPLATE;
open(TEMPLATE, ">$estdir/$cgi.conf") ||
error("write $estdir/$cgi.conf: $!");
my $template=HTML::Template->new(
filename => "$config{templatedir}/estseek.conf"
);
eval q{use Cwd 'abs_path'};
$template->param(
index => $estdir,
tmplfile => "$estdir/$cgi.tmpl",
destdir => abs_path($config{destdir}),
url => $config{url},
);
print TEMPLATE $template->output;
close TEMPLATE;
$cgi="$estdir/".basename($config{cgiurl});
unlink($cgi);
symlink("/usr/lib/estraier/estseek.cgi", $cgi) ||
error("symlink $cgi: $!");
} # }}}
sub estcmd ($;@) { #{{{
my @params=split(' ', shift);
push @params, "-cl", "$config{wikistatedir}/hyperestraier";
if (@_) {
push @params, "-";
}
my $pid=open(CHILD, "|-");
if ($pid) {
# parent
foreach (@_) {
print CHILD "$_\n";
}
close(CHILD) || error("estcmd @params exited nonzero: $?");
}
else {
# child
open(STDOUT, "/dev/null"); # shut it up (closing won't work)
exec("estcmd", @params) || error("can't run estcmd");
}
} #}}}
1

View File

@ -1,6 +1,7 @@
#!/usr/bin/perl #!/usr/bin/perl
# Ikiwiki skeleton plugin. Replace "skeleton" with the name of your plugin # Ikiwiki skeleton plugin. Replace "skeleton" with the name of your plugin
# in the lines below, and flesh out the code to make it do something. # in the lines below, remove hooks you don't use, and flesh out the code to
# make it do something.
package IkiWiki::Plugin::skeleton; package IkiWiki::Plugin::skeleton;
use warnings; use warnings;
@ -8,14 +9,44 @@ use strict;
use IkiWiki; use IkiWiki;
sub import { #{{{ sub import { #{{{
IkiWiki::hook(type => "checkconfig", id => "skeleton",
call => \&checkconfig);
IkiWiki::hook(type => "preprocess", id => "skeleton", IkiWiki::hook(type => "preprocess", id => "skeleton",
call => \&preprocess); call => \&preprocess);
IkiWiki::hook(type => "delete", id => "skeleton",
call => \&delete);
IkiWiki::hook(type => "render", id => "skeleton",
call => \&render);
IkiWiki::hook(type => "cgi", id => "skeleton",
call => \&cgi);
} # }}} } # }}}
sub checkconfig () { #{{{
IkiWiki::debug("skeleton plugin checkconfig");
} #}}}
sub preprocess (@) { #{{{ sub preprocess (@) { #{{{
my %params=@_; my %params=@_;
return "skeleton plugin result"; return "skeleton plugin result";
} # }}} } # }}}
sub delete (@) { #{{{
my @files=@_;
IkiWiki::debug("skeleton plugin told that files were deleted: @files");
} #}}}
sub render (@) { #{{{
my @files=@_;
IkiWiki::debug("skeleton plugin told that files were rendered: @files");
} #}}}
sub cgi ($) { #{{{
my $cgi=shift;
IkiWiki::debug("skeleton plugin running in cgi");
} #}}}
1 1

View File

@ -206,9 +206,7 @@ sub genpage ($$$) { #{{{
$u=~s/\[\[file\]\]/$pagesources{$page}/g; $u=~s/\[\[file\]\]/$pagesources{$page}/g;
$template->param(historyurl => $u); $template->param(historyurl => $u);
} }
if ($config{hyperestraier}) { $template->param(headercontent => $config{headercontent});
$template->param(hyperestraierurl => cgiurl());
}
$template->param( $template->param(
title => $title, title => $title,
@ -300,57 +298,6 @@ sub prune ($) { #{{{
} }
} #}}} } #}}}
sub estcfg () { #{{{
my $estdir="$config{wikistatedir}/hyperestraier";
my $cgi=basename($config{cgiurl});
$cgi=~s/\..*$//;
open(TEMPLATE, ">$estdir/$cgi.tmpl") ||
error("write $estdir/$cgi.tmpl: $!");
print TEMPLATE misctemplate("search",
"<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n");
close TEMPLATE;
open(TEMPLATE, ">$estdir/$cgi.conf") ||
error("write $estdir/$cgi.conf: $!");
my $template=HTML::Template->new(
filename => "$config{templatedir}/estseek.conf"
);
eval q{use Cwd 'abs_path'};
$template->param(
index => $estdir,
tmplfile => "$estdir/$cgi.tmpl",
destdir => abs_path($config{destdir}),
url => $config{url},
);
print TEMPLATE $template->output;
close TEMPLATE;
$cgi="$estdir/".basename($config{cgiurl});
unlink($cgi);
symlink("/usr/lib/estraier/estseek.cgi", $cgi) ||
error("symlink $cgi: $!");
} # }}}
sub estcmd ($;@) { #{{{
my @params=split(' ', shift);
push @params, "-cl", "$config{wikistatedir}/hyperestraier";
if (@_) {
push @params, "-";
}
my $pid=open(CHILD, "|-");
if ($pid) {
# parent
foreach (@_) {
print CHILD "$_\n";
}
close(CHILD) || error("estcmd @params exited nonzero: $?");
}
else {
# child
open(STDOUT, "/dev/null"); # shut it up (closing won't work)
exec("estcmd", @params) || error("can't run estcmd");
}
} #}}}
sub refresh () { #{{{ sub refresh () { #{{{
# find existing pages # find existing pages
my %exists; my %exists;
@ -516,19 +463,15 @@ FILE: foreach my $file (@files) {
} }
} }
if ($config{hyperestraier} && (%rendered || @del)) { if (@del && exists $hooks{delete}) {
debug("updating hyperestraier search index"); foreach my $id (keys %{$hooks{delete}}) {
if (%rendered) { $hooks{delete}{$id}{call}->(@del);
estcmd("gather -cm -bc -cl -sd",
map { $config{destdir}."/".$renderedfiles{pagename($_)} }
keys %rendered);
} }
if (@del) { }
estcmd("purge -cl"); if (%rendered && exists $hooks{render}) {
foreach my $id (keys %{$hooks{render}}) {
$hooks{render}{$id}{call}->(keys %rendered);
} }
debug("generating hyperestraier cgi config");
estcfg();
} }
} #}}} } #}}}

View File

@ -21,15 +21,20 @@ sub setup_standard {
if (! $config{refresh}) { if (! $config{refresh}) {
debug("generating wrappers.."); debug("generating wrappers..");
my @wrappers=@{$setup{wrappers}};
delete $setup{wrappers};
my %startconfig=(%config); my %startconfig=(%config);
foreach my $wrapper (@{$setup{wrappers}}) { foreach my $wrapper (@wrappers) {
%config=(%startconfig, verbose => 0, %setup, %{$wrapper}); %config=(%startconfig, verbose => 0, %setup, %{$wrapper});
checkconfig(); checkconfig();
gen_wrapper(); gen_wrapper();
} }
%config=(%startconfig); %config=(%startconfig);
delete $config{wrappers};
} }
else {
delete $setup{wrappers};
}
foreach my $c (keys %setup) { foreach my $c (keys %setup) {
if (defined $setup{$c}) { if (defined $setup{$c}) {
if (! ref $setup{$c}) { if (! ref $setup{$c}) {

View File

@ -51,6 +51,7 @@ EOF
my $configstring=Data::Dumper->Dump([\%config], ['*config']); my $configstring=Data::Dumper->Dump([\%config], ['*config']);
$configstring=~s/\\/\\\\/g; $configstring=~s/\\/\\\\/g;
$configstring=~s/"/\\"/g; $configstring=~s/"/\\"/g;
$configstring=~s/\n/\\\n/g;
open(OUT, ">$wrapper.c") || error("failed to write $wrapper.c: $!");; open(OUT, ">$wrapper.c") || error("failed to write $wrapper.c: $!");;
print OUT <<"EOF"; print OUT <<"EOF";

4
debian/NEWS vendored
View File

@ -5,6 +5,10 @@ ikiwiki (1.1) unstable; urgency=low
be changed to set rcs => "svn"; if your setup file sets svn => 0 be changed to set rcs => "svn"; if your setup file sets svn => 0
then change it to use rcs => "" to disable svn. then change it to use rcs => "" to disable svn.
The --hyperestraier switch is gone too. To enable searching, turn on the
search plugin, by passing --plugin=search or through the plugin setting in
the config file.
You will need to rebuild your wiki when upgrading to this version. You will need to rebuild your wiki when upgrading to this version.
If you listed your wiki in /etc/ikiwiki/wikilist this will be done If you listed your wiki in /etc/ikiwiki/wikilist this will be done
automatically. automatically.

4
debian/changelog vendored
View File

@ -11,7 +11,7 @@ ikiwiki (1.1) UNRELEASED; urgency=low
* Which means that more than one blog is now supported to appear on a * Which means that more than one blog is now supported to appear on a
single page. (With some limitations, like only the last one getting an single page. (With some limitations, like only the last one getting an
rss file.) rss file.)
* Added plugin system, currently only supporting for PreProcessorDirectives. * Added a plugin system.
* Added a pagecount plugin, enabled by default. * Added a pagecount plugin, enabled by default.
* Support PreProcessorDirectives with no parameters, ie "[[pagecount ]]". * Support PreProcessorDirectives with no parameters, ie "[[pagecount ]]".
* Fixed/optimised backlinks code, to avoid rebuilding pages to update * Fixed/optimised backlinks code, to avoid rebuilding pages to update
@ -37,6 +37,8 @@ ikiwiki (1.1) UNRELEASED; urgency=low
* Load whatever rcs module is specified, so new ones can be just dropped in * Load whatever rcs module is specified, so new ones can be just dropped in
as plugins and work. (Well, in theory.) as plugins and work. (Well, in theory.)
* Add some basic docs about writing RCS modules. * Add some basic docs about writing RCS modules.
* Broke search capability out into a plugin, removed the --hyperestraier
switch.
-- Joey Hess <joeyh@debian.org> Tue, 2 May 2006 14:13:59 -0400 -- Joey Hess <joeyh@debian.org> Tue, 2 May 2006 14:13:59 -0400

View File

@ -1,3 +1,3 @@
[Hyper Estraier](http://hyperestraier.sourceforge.net/) is a full text search engine. Ikiwiki can be configured to use it as the search engine for the wiki (see [[usage]]). This makes ikiwiki call Hyper Ertaier to update its index of pages each time a change is made to the wiki. [Hyper Estraier](http://hyperestraier.sourceforge.net/) is a full text
search engine. Ikiwiki can be configured to use it as the search engine for
It's possible to configure Hyper Estraier via one of ikiwiki's [[templates]]. the wiki, using the [[search_plugin|plugins/search]].

View File

@ -48,10 +48,8 @@ use IkiWiki::Setup::Standard {
#anonok => 1, #anonok => 1,
# Generate rss feeds for pages? # Generate rss feeds for pages?
rss => 1, rss => 1,
# Use the Hyper Estraier search engine?
#hyperestraier => 1,
# Sanitize html? # Sanitize html?
sanitize => 1, sanitize => 1,
# To change the enabled plugins, edit this list # To change the enabled plugins, edit this list
#plugin => [qw{pagecount inline brokenlinks}], #plugin => [qw{pagecount inline brokenlinks hyperestraier}],
} }

View File

@ -0,0 +1,5 @@
This plugin is included in ikiwiki, but is not enabled by default. It adds
full text search to ikiwiki, using the [[HyperEstraier]] engine.
It's possible to configure Hyper Estraier via one of ikiwiki's
[[templates]].

View File

@ -172,11 +172,6 @@ These options configure the wiki.
Enables the use of the specified plugin in the wiki. See [[plugins]] for Enables the use of the specified plugin in the wiki. See [[plugins]] for
details. Note that plugin names are case sensative. details. Note that plugin names are case sensative.
* --hyperestraier
Enables use of the [[HyperEstraier]] search engine for full test page
searches.
* --verbose * --verbose
Be vebose about what is being done. Be vebose about what is being done.

View File

@ -34,7 +34,6 @@ sub getconfig () { #{{{
rebuild => 0, rebuild => 0,
refresh => 0, refresh => 0,
getctime => 0, getctime => 0,
hyperestraier => 0,
wrapper => undef, wrapper => undef,
wrappermode => undef, wrappermode => undef,
svnrepo => undef, svnrepo => undef,
@ -47,6 +46,7 @@ sub getconfig () { #{{{
adminuser => undef, adminuser => undef,
adminemail => undef, adminemail => undef,
plugin => [qw{inline}], plugin => [qw{inline}],
headercontent => '',
); );
eval q{use Getopt::Long}; eval q{use Getopt::Long};
@ -61,7 +61,6 @@ sub getconfig () { #{{{
"rcs=s" => \$config{rcs}, "rcs=s" => \$config{rcs},
"no-rcs" => sub { $config{rcs}="" }, "no-rcs" => sub { $config{rcs}="" },
"anonok!" => \$config{anonok}, "anonok!" => \$config{anonok},
"hyperestraier" => \$config{hyperestraier},
"rss!" => \$config{rss}, "rss!" => \$config{rss},
"cgi!" => \$config{cgi}, "cgi!" => \$config{cgi},
"notify!" => \$config{notify}, "notify!" => \$config{notify},
@ -104,6 +103,9 @@ sub getconfig () { #{{{
# wrapper passes a full config structure in the environment # wrapper passes a full config structure in the environment
# variable # variable
eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS}); eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS});
if ($@) {
error("WRAPPED_OPTIONS: $@");
}
checkconfig(); checkconfig();
} }
} #}}} } #}}}

View File

@ -15,15 +15,7 @@
</TMPL_LOOP> </TMPL_LOOP>
<TMPL_VAR TITLE> <TMPL_VAR TITLE>
</h1> </h1>
<TMPL_IF NAME="HYPERESTRAIERURL"> <TMPL_VAR HEADERCONTENT>
<form method="get" action="<TMPL_VAR HYPERESTRAIERURL>" id="searchform">
<div>
<input type="text" name="phrase" value="" size="16" />
<input type="hidden" name="enc" value="UTF-8" />
<input type="hidden" name="do" value="hyperestraier" />
</div>
</form>
</TMPL_IF>
</div> </div>
<div id="actions"> <div id="actions">