Major change:
authorDobrica Pavlinusic <dpavlin@rot13.org>
Sat, 17 Apr 2004 20:40:28 +0000 (20:40 +0000)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Sat, 17 Apr 2004 20:40:28 +0000 (20:40 +0000)
I no longer user HTML::Pager, SWISH and SWISH::Fork modules,
but SWISH::API (new interface to swish 2.4.x, which is required) and own
implementation of pager.

That saves round-trips of all results from swish-e to memory and to
HTML::Pager so this produces also significant speedup when result set is
large (tipically if you entered just a letter or two with huge number of
records).

git-svn-id: file:///home/dpavlin/private/svn/webpac/trunk@304 13eb9ef6-21d5-0310-b721-a9d68796d827

INSTALL
TODO
WebPac.pm
doc/CPAN.modules

diff --git a/INSTALL b/INSTALL
index 89cedd5..5bbdaa5 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -52,11 +52,9 @@ don't work for you.
        Config::IniFiles
        DBD::Pg                 or some other DBD driver like DBD::SQLite
        CGI::Application
-       HTML::Pager
        HTML::Template
        HTML::FillInForm
-       SWISH
-       SWISH::Fork             and of course, swish-e executable
+       SWISH::API
        XML::Simple
        Text::Iconv
        TDB_File
@@ -100,10 +98,8 @@ don't work for you.
    because they are not part of Debian distribution:
 
        CGI::Application
-       HTML::Pager
        HTML::FillInForm
-       SWISH
-       SWISH::Fork
+       SWISH::API
 
    and optionally some of those modules:
 
diff --git a/TODO b/TODO
index 39a3c26..e0d8a30 100644 (file)
--- a/TODO
+++ b/TODO
@@ -35,12 +35,6 @@ This are notes about WWW interface:
 
 ---------------------------------------------------------------------------
 
-Fix stupid things with HTML::Pager and HTML::Template. Since communication
-between swish and HTML::Pager isn't as good as it should be, I must include
-all fields in output every time, creating huge html comments when you want
-just hits (I could turn off die_on_bad_params in HTML::Template, but there
-should be better way...)
-
 - statistics for each library
 
 + put links on the titles on the short results page
index 6484760..8139173 100644 (file)
--- a/WebPac.pm
+++ b/WebPac.pm
@@ -3,13 +3,13 @@ package WebPac;
 use base 'CGI::Application';
 use strict;
 
-use HTML::Pager;
 use HTML::FillInForm;
-use SWISH;
+use SWISH::API;
 use Text::Iconv;
 use DBI;
 use Config::IniFiles;
 use Text::Unaccent;
+use Data::Pageset;
 
 use lib '..';
 use index_DBI_cache;
@@ -30,6 +30,9 @@ my $MIN_WILDCARD =$cfg_global->val('webpac', 'min_wildcard') || 1;
 my $TEMPLATE =$cfg_global->val('webpac', 'template');
 my $UNAC_FILTER =$cfg_global->val('global', 'unac_filter');
 my $BASE_PATH =$cfg_global->val('webpac', 'base_path');
+# for pager
+my $pages_per_set = $cfg_global->val('webpac', 'pages_per_set') || 10;
+
 
 if ($UNAC_FILTER) {
        require $UNAC_FILTER;
@@ -112,6 +115,88 @@ sub in_template {
        }
 }
 
+#--------------------------------------------------------------------------
+
+#
+# make pager navigation and fill template variables
+# compatibile with HTML::Pager
+#
+
+sub make_pager($$$) {
+       my ($q,$tmpl,$pager) = @_;
+
+       #
+       # pager navigation
+       #
+       my ($pager_prev,$pager_next, $pager_jump) = ('','','');
+
+       my $nav_fmt=qq{ <a href="%s">%s</a> };
+
+       if ($pager->current_page() > $pager->first_page) {
+               $q->param('PAGER_offset', $pager->current_page - 1);
+               $pager_prev .= sprintf($nav_fmt,$q->url(-relative=>1, -query=>1),'&lt;&lt;');
+       }
+
+       if ($pager->previous_set) {
+               $q->param('PAGER_offset', $pager->previous_set);
+               $pager_prev .= sprintf($nav_fmt,$q->url(-relative=>1, -query=>1),'..');
+       }
+
+
+       foreach my $p (@{$pager->pages_in_set()}) {
+               next if ($p < 0);
+               if($p == $pager->current_page()) {
+                       $pager_jump .= "<b>$p</b> ";
+               } else {
+                       $q->param('PAGER_offset', $p);
+                       $pager_jump .= sprintf($nav_fmt,$q->url(-relative=>1, -query=>1),$p);
+               }
+       }
+
+       if ($pager->next_set) {
+               $q->param('PAGER_offset', $pager->next_set);
+               $pager_next .= sprintf($nav_fmt,$q->url(-relative=>1, -query=>1),'..');
+       }
+
+       if ($pager->current_page() < $pager->last_page) {
+               $q->param('PAGER_offset', $pager->current_page + 1);
+               $pager_next .= sprintf($nav_fmt,$q->url(-relative=>1, -query=>1),'&gt;&gt;');
+       }
+
+       $tmpl->param('PAGER_PREV', $pager_prev);
+       $tmpl->param('PAGER_JUMP', $pager_jump);
+       $tmpl->param('PAGER_NEXT', $pager_next);
+
+}
+
+#
+# put persisten variables in template
+#
+
+sub make_pager_vars {
+       my $q = shift @_;
+       my $tmpl = shift @_;
+       my @persist_vars = @_;
+       my $hidden_vars = '';
+       foreach my $v (@persist_vars) {
+               $hidden_vars .= '<input type="hidden" name="'.$v.'" value="'.$q->param($v).'"/>'."\n";
+       }
+
+       $tmpl->param('PAGER_HIDDEN', $hidden_vars);
+       $tmpl->param('PAGER_JAVASCRIPT', qq{
+<SCRIPT LANGUAGE="Javascript">
+<!-- Begin
+       // dummy emulator for HTML::Pager templates
+       function PAGER_set_offset_and_submit() {
+               return true;
+       }
+// End -->
+</script>  
+       });
+}
+
+#--------------------------------------------------------------------------
+
 sub show_search_form {
        my $self = shift;
 
@@ -132,8 +217,6 @@ sub show_results_list {
 
        my $q = $self->query();
 
-       my @swish_results;      # results from swish
-
        # load template for this page
 
        my @s_arr;      # all queries are located here
@@ -141,8 +224,8 @@ sub show_results_list {
        my @path_arr = $q->param('path');
        my $full = $q->param('full');
 
-       my @persist_vars = ( 'rm' ); 
-       my @url_params = ( 'rm=results', 'show_full=1', 'last_PAGER_offset='.$q->param('PAGER_offset') || 0 );
+       my @persist_vars = ( 'rm' );
+       my @url_params = ( 'rm=results', 'show_full=1', 'last_PAGER_offset='.($q->param('PAGER_offset') || 0) );
 
        # support parametars "f" and "v" for start
        for(my $i = ""; $i <=30; $i++) {
@@ -218,6 +301,8 @@ sub show_results_list {
 
        my $tmpl = $self->load_tmpl(url_ex($q,'results.html'), global_vars => 1);
 
+       $tmpl->param('url_params',"?".join("&",@url_params));
+
        sub esc_html {
                my $html = shift;
                $html =~ s/</&lt;/g;
@@ -231,28 +316,6 @@ sub show_results_list {
                push @persist_vars, "sort";
        }
 
-       # call swish
-       my $sh = SWISH->connect('Fork',
-               prog     => $SWISH,
-               indexes  => $INDEX,
-               properties  => [qw/swishdocpath swishrank swishtitle headline html/],
-               results  => sub {
-                       my ($sh,$hit) = @_;
-
-                       push @swish_results, {
-                               nr => ($#swish_results + 2),
-                               path => $hit->swishdocpath,
-                               headline => esc_html($from_utf8->convert($hit->headline)),
-                               html => back2html($from_utf8->convert($hit->html)),
-                               rank => $hit->swishrank };
-
-               },
-               #startnum => 0,
-               maxhits => $MAX_HITS,
-               sortorder => $sort,
-       );
-
-       die $SWISH::errstr unless $sh;
        # construct swish query
        my $sw_q = join(" and ",@s_arr);
        if (@path_arr && $q->param('show_full')) {
@@ -267,7 +330,19 @@ sub show_results_list {
                $tmpl->param('full',0);
        }
 
-       my $hits = $sh->query($sw_q);
+       # create new swish instance
+       my $swish = SWISH::API->new($INDEX);
+       $swish->AbortLastError if $swish->Error;
+
+       # execute query and get number of results from SWISH-E
+       my $search = $swish->New_Search_Object;
+
+       $search->SetSort($sort);
+
+       my $results = $search->Execute($sw_q);
+       $swish->AbortLastError if $swish->Error;
+
+       my $hits = $results->Hits;
 
        $tmpl->param('hits',$hits);
        $tmpl->param('search',$sw_q);
@@ -275,41 +350,52 @@ sub show_results_list {
        $tmpl->param('PAGER_offset',$q->param("PAGER_offset") || 0);
        $tmpl->param('last_PAGER_offset',$q->param("last_PAGER_offset") || 0);
 
-       $tmpl->param('url_params',"?".join("&",@url_params));
+       #
+       # build pager
+       #
 
-       # create a Pager object
-       my $pager = HTML::Pager->new(
-               # required parameters
-               query => $q,
-               get_data_callback => sub {
-                       my ($offset, $rows) = @_;
-
-                       my @result;
-                       for (my $i=0; $i<$rows; $i++) {
-                               my $r = $swish_results[$offset+$i];
-                               if ($r && $tmpl->param('full')) {
-                                       push @result, $r;
-                               } elsif ($r) {
-                                       # if not full output, skip html
-                                       delete $r->{html};
-                                       push @result, $r;
-                               }
-                       }
-                       return \@result;
-               },
-               rows => $hits,
-               page_size => $ON_PAGE,
-               # some optional parameters
-               persist_vars => [ @persist_vars ],
-               #cell_space_color => '#000000',
-               #cell_background_color => '#ffffff',
-               #nav_background_color => '#dddddd',
-               #javascript_presubmit => 'last_minute_javascript()',
-               debug => 1,
-               template => $tmpl,
-       );
+       my $current_page = $q->param('PAGER_offset') || 1;
+
+       my $pager = Data::Pageset->new({
+               'total_entries' => $hits,
+               'entries_per_page' => $ON_PAGE,
+               'current_page' => $current_page,
+               'pages_per_set' => $pages_per_set,
+       });
+
+       $results->SeekResult( $pager->first - 1 );
+
+       # get number of entries on this page
+       my $i = $pager->entries_on_this_page;
+
+       # results from swish for template
+       my @pager_data_list;
+
+       for(my $i=$pager->first; $i<=$pager->last; $i++) {
 
-       my $html = $pager->output;
+               my $result = $results->NextResult;
+               last if (! $result);
+
+               my $r = {
+                       nr => $i,
+                       path => $result->Property('swishdocpath'),
+                       headline => esc_html($from_utf8->convert($result->Property('headline'))),
+                       rank => $result->Property('swishrank')
+               };
+
+               $r->{html} = back2html($from_utf8->convert($result->Property('html'))) if ($q->param('show_full'));
+
+               push @pager_data_list, $r;
+       }
+
+
+
+       # put something in template
+       make_pager($q, $tmpl, $pager);
+       make_pager_vars($q, $tmpl, @persist_vars);
+       $tmpl->param('PAGER_DATA_LIST', \@pager_data_list);
+
+       my $html = $tmpl->output;
 
        return in_template($q,$html);
 }
@@ -333,6 +419,7 @@ sub show_index {
        );
 
        my $total = $index->count($field,$limit);
+
        if (! $total) {
                my $tmpl = $self->load_tmpl(url_ex($q,'no_index.html'));
                $tmpl->param('field',$field);
@@ -350,26 +437,26 @@ sub show_index {
 #              $q->param("Pager_offet)
 #      }
 
-       my $pager = HTML::Pager->new(
-               query => $q,
-               get_data_callback => sub {
-                       my ($offset, $rows) = @_;
-
-                       my @result = $index->fetch($field,$limit, $offset, $rows);
-                       return \@result;
-               },
-               rows => $total,
-               page_size => $ON_PAGE,
-               persist_vars => [
-                       'rm', 
-                       "f$i", "v$i", "f".$i."_index", 
-                       'offset',
-                       ],
-               debug => 1,
-               template => $tmpl,
-       );
 
-       return in_template($q,$pager->output);
+       #
+       # build pager
+       #
+       my $pager = Data::Pageset->new({
+               'total_entries' => $total,
+               'entries_per_page' => $ON_PAGE,
+               'current_page' => $q->param('PAGER_offset') || 1,
+               'pages_per_set' => $pages_per_set
+       });
+
+       my @persist_vars = qw{rm f$i v$i f$i_index offset};
+
+       make_pager($q, $tmpl, $pager);
+       make_pager_vars($q, $tmpl, @persist_vars);
+
+       my @pager_data_list = $index->fetch($field,$limit, $pager->first - 1, $pager->entries_on_this_page);
+       $tmpl->param('PAGER_DATA_LIST', \@pager_data_list);
+
+       return in_template($q,$tmpl->output);
 }
 
 1;
index 752ff62..6ea70f9 100644 (file)
@@ -12,7 +12,6 @@ Text::Unaccent from http://www.senga.org/unac/
 
 Modules which are used:
 CGI::Application
-HTML::Pager
 HTML::Template
 HTML::FillInForm
 Spreadsheet::ParseExcel