koha-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Koha-cvs] koha/opac opac-zoomsearch.pl


From: Antoine Farnault
Subject: [Koha-cvs] koha/opac opac-zoomsearch.pl
Date: Fri, 11 Aug 2006 15:55:45 +0000

CVSROOT:        /sources/koha
Module name:    koha
Changes by:     Antoine Farnault <toins>        06/08/11 15:55:45

Added files:
        opac           : opac-zoomsearch.pl 

Log message:
        allow to search with zoom on opac. (sync with dev_week)

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/koha/opac/opac-zoomsearch.pl?cvsroot=koha&rev=1.2

Patches:
Index: opac-zoomsearch.pl
===================================================================
RCS file: opac-zoomsearch.pl
diff -N opac-zoomsearch.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ opac-zoomsearch.pl  11 Aug 2006 15:55:45 -0000      1.2
@@ -0,0 +1,501 @@
+#!/usr/bin/perl
+
+# Copyright 2006 Liblime
+#
+# This file is part of Koha.
+# 
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details. 
+#
+# You should have received a copy of the GNU General Public License along with
+# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+# load our Koha modules
+use C4::Context;
+use C4::Interface::CGI::Output;
+use C4::Auth;
+use C4::Search;
+use C4::Biblio;
+use C4::Koha;
+use POSIX qw(ceil floor);
+
+# load other modules
+use HTML::Template;
+use CGI;
+use strict; 
+
+my $query=new CGI;
+my $op = $query->param('op'); # show the search form or execute the search
+
+# expanded facet?
+my $expanded_facet = $query->param('expand');
+
+### Gather up all our search queries
+## CQL
+my $cql_query = $query->param('cql_query');
+
+## CCL
+my @previous_ccl_queries; # array of hashes
+my @previous_ccl_queries_array = $query->param('previous_ccl_queries');
+
+my @ccl_query = $query->param('ccl_query');
+my $ccl_query;
+foreach my $ccl (@ccl_query) {
+       $ccl_query.="$ccl " if $ccl;
+}
+push @previous_ccl_queries_array, $ccl_query;
+# put the queries in a form the template can use
+my $previous_ccl_queries_hash;
+foreach my $ccl (@previous_ccl_queries_array) {
+       if ($ccl) {
+       my %row =(
+               value => $ccl
+               );
+       push @previous_ccl_queries, %row;
+       }
+}
+## PQF
+my $pqf_query = $query->param('pqf_query');
+
+my @newresults;
+my ($template,$borrowernumber,$cookie);
+my @forminputs;                # this is for the links to navigate among the 
results when they are more than the maximum number of results per page
+my $searchdesc; 
+my $search_type = $query->param('search_type');
+
+my $dbh = C4::Context->dbh;
+## Get Itemtypes (Collection Codes)
+my $itemtypequery="Select itemtype,description from itemtypes order by 
description";    
+my $sth=$dbh->prepare($itemtypequery);
+$sth->execute;
+my @itemtypeloop;
+my %itemtypes;
+while (my ($value,$lib) = $sth->fetchrow_array) {
+        my %row =(
+            value => $value,
+            description => $lib,
+            );
+        push @itemtypeloop, \%row;
+
+}
+$sth->finish;
+
+## Get Branches
+my @branches;
+my @select_branch;
+my %select_branches;
+my $branches = getallbranches();
+my @branchloop;
+foreach my $thisbranch (keys %$branches) {
+               my $selected = 1 if (C4::Context->userenv && ($thisbranch eq 
C4::Context->userenv->{branch}));            
+               my %row =(
+               value => $thisbranch,
+               selected => $selected,
+               branchname => $branches->{$thisbranch}->{'branchname'},
+               );
+        push @branchloop, \%row;
+}
+
+## Check if we're searching
+if ($op eq 'get_results') { # Yea, we're searching, load the results template
+       ($template, $borrowernumber, $cookie)
+               = get_template_and_user({template_name => "opac-results.tmpl",
+                                         query => $query,
+                                         type => "opac",
+                                         authnotrequired => 1,});
+
+       my $number_of_results = $query->param('results_per_page');
+       $number_of_results = 20 unless ($number_of_results); #this could be a 
parameter with 20 50 or 100 results per page
+       my $startfrom = $query->param('startfrom');
+       ($startfrom) || ($startfrom=0);
+
+       ## OK, WE'RE SEARCHING
+       # STEP 1. We're a CGI script,so first thing to do is get the
+       # query into PQF format so we can use the Koha API properly
+       my ($error,$pqf_sort_by, $pqf_prox_ops, $pqf_bool_ops, $nice_query);
+       ($error,$pqf_sort_by, $pqf_prox_ops, $pqf_bool_ops, $pqf_query, 
$nice_query)= cgi2pqf($query);
+       my $then_sort_by = $query->param('then_sort_by');
+       # implement a query history
+
+       # lets store the query details in an array for later
+       push @forminputs, { field => "cql_query" , value => $cql_query} ;
+       push @forminputs, { field => "ccl_query" , value => $ccl_query} ;
+       push @forminputs, { field => 'pqf_sort_by', value => $pqf_sort_by} ;
+       push @forminputs, { field => 'pqf_prox_ops', value => $pqf_prox_ops};
+       push @forminputs, { field => 'pqf_bool_ops' , value => $pqf_bool_ops};
+       push @forminputs, { field => 'pqf_query' , value => $pqf_query };
+       $searchdesc=$cql_query.$ccl_query.$nice_query; # FIXME: this should be 
a more use-friendly string
+
+       # STEP 2. OK, now we have PQF, so we can pass off the query to
+       # the API
+       my ($count,@results,$facets);
+
+       # queries are handled differently, so alert our API and pass in the 
variables
+       if ($ccl_query) { # CCL
+               if ($query->param('scan')) {
+                       ($error,$count, $facets,@results) = 
searchZOOM('scan','ccl',$ccl_query,$number_of_results,$startfrom,$then_sort_by,$expanded_facet);
+                       $template->param(scan => 1);
+               } else {
+                       ($error,$count,$facets,@results) = 
searchZOOM('search','ccl',$ccl_query,$number_of_results,$startfrom,$then_sort_by,$expanded_facet);
+               }
+       } elsif ($query->param('cql_query')) { # CQL
+               if ($query->param('scan')) {
+                       ($error,$count,$facets,@results) = 
searchZOOM('scan','cql',$cql_query,$number_of_results,$startfrom,$then_sort_by,$expanded_facet);
+                       $template->param(scan => 1);
+               } else {
+                       ($error,$count,$facets,@results) = 
searchZOOM('search','cql',$cql_query,$number_of_results,$startfrom,$then_sort_by,$expanded_facet);
+               }
+       } else { # we're in PQF territory now
+               if ($query->param('scan')) {
+                       $template->param(scan => 1);
+                       ($error,$count,$facets,@results) = 
searchZOOM('scan','pqf',"$pqf_sort_by $pqf_prox_ops $pqf_bool_ops 
$pqf_query",$number_of_results,$startfrom,$then_sort_by,$expanded_facet);
+               } else {
+                       ($error,$count,$facets,@results) = 
searchZOOM('search','pqf',"$pqf_sort_by $pqf_prox_ops $pqf_bool_ops 
$pqf_query",$number_of_results,$startfrom,$then_sort_by,$expanded_facet);
+               }
+       }
+       @newresults=searchResults( 
$searchdesc,$number_of_results,$count,@results) ;
+
+       # How many did we get back?
+       my $num = scalar(@newresults);
+
+       # sorting out which results to display.
+       # the result number to start to show
+       $template->param(starting => $startfrom+1);
+       $template->param(ending => $startfrom+$number_of_results);
+       # the result number to end to show
+       ($startfrom+$num<=$count) ? ($template->param(endat => 
$startfrom+$num)) : ($template->param(endat => $count));
+       # the total results found
+       $template->param(total => $count);
+       $template->param(FORMINPUTS => address@hidden);
+       #$template->param(pqf_query => $pqf_query);
+       $template->param(ccl_query => $ccl_query);
+       $template->param(searchdesc => $searchdesc );
+       $template->param(results_per_page =>  $number_of_results );
+       $template->param(SEARCH_RESULTS => address@hidden);
+       $template->param(PREVIOUS_CCL_QUERIES => address@hidden);
+       $template->param(facets_loop => $facets);
+
+       #this is to show the page numbers to navigate among the results, 
whether it has to show the number highlighted or not
+       my $numbers;
+       @$numbers = ();
+       my $pg = 1;
+       if (defined($query->param('pg'))) {
+               $pg = $query->param('pg');
+       }
+       my $start = 0;
+       
+       $start = ($pg - 1) * $number_of_results;
+       my $pages = ceil($count / $number_of_results);
+       my $total_pages = ceil($count / $number_of_results);
+       my $url;
+       if ($pg > 1) {
+               $url = $pg - 1;
+               push @$numbers, {               
+                               number => "&lt;&lt;", 
+                               highlight => 0 , 
+                               startfrom => 0, 
+                               pg => '1' };
+
+               push @$numbers, {               
+                               number => "&lt;", 
+                               highlight => 0 , 
+                               startfrom => ($url-1)*$number_of_results, 
+                               pg => $url };
+       }
+       my $current_ten = $pg / 10;
+       if ($current_ten == 0) {
+                $current_ten = 0.1;           # In case it's in ten = 0
+       } 
+       my $from = $current_ten * 10; # Calculate the initial page
+       my $end_ten = $from + 9;
+       my $to;
+       if ($pages > $end_ten) {
+               $to = $end_ten;
+       } else {
+               $to = $pages;
+       }
+       for (my $i =$from; $i <= $to ; $i++) {
+               if ($i == $pg) {   
+                       if ($count > $number_of_results) {
+                               push @$numbers, { 
+                                               number => $i, 
+                                               highlight => 1 , 
+                                               startfrom => 
($i-1)*$number_of_results , 
+                                               pg => $i };
+                       }
+               } else {
+                       push @$numbers, {       
+                                               number => $i, 
+                                               highlight => 0 , 
+                                               startfrom => 
($i-1)*$number_of_results , 
+                                               pg => $i };
+               }
+       }                                                       
+       if ($pg < $pages) {
+                $url = $pg + 1;
+               push @$numbers, {               
+                                               number => "&gt;", 
+                                               highlight => 0 , 
+                                               startfrom => 
($url-1)*$number_of_results, 
+                                               pg => $url };
+
+               push @$numbers, {               
+                                               number => "&gt;&gt;", 
+                                               highlight => 0 , 
+                                               startfrom => 
($total_pages-1)*$number_of_results, 
+                                               pg => $total_pages};
+       }
+
+       $template->param(                       
+                                               pqf_sort_by => $pqf_sort_by,
+                                               pqf_query => "$pqf_prox_ops 
$pqf_bool_ops $pqf_query",
+                                               numbers => $numbers);
+
+
+    
$template->param('Disable_Dictionary'=>C4::Context->preference("Disable_Dictionary"))
 if (C4::Context->preference("Disable_Dictionary"));
+    my $scan_use = $query->param('use1');
+    $template->param(
+                       #classlist => $classlist,
+                       suggestion => C4::Context->preference("suggestion"),
+                       virtualshelves => 
C4::Context->preference("virtualshelves"),
+                       LibraryName => C4::Context->preference("LibraryName"),
+                       OpacNav => C4::Context->preference("OpacNav"),
+                       opaccredits => C4::Context->preference("opaccredits"),
+                       AmazonContent => 
C4::Context->preference("AmazonContent"),
+                       opacsmallimage => 
C4::Context->preference("opacsmallimage"),
+                       opaclayoutstylesheet => 
C4::Context->preference("opaclayoutstylesheet"),
+                       opaccolorstylesheet => 
C4::Context->preference("opaccolorstylesheet"),
+                       scan_use => $scan_use,
+                       search_error => $error,
+    );
+
+       ## Now let's find out if we have any supplemental data to show the user
+       #  and in the meantime, save the current query for statistical 
purposes, etc.
+       my $koha_spsuggest; # a flag to tell if we've got suggestions coming 
from Koha
+       my @koha_spsuggest; # place we store the suggestions to be returned to 
the template as LOOP
+       my $phrases = $searchdesc;
+       my $ipaddress;
+       
+       if ( C4::Context->preference("kohaspsuggest") ) {
+               eval {
+                       my $koha_spsuggest_dbh;
+                       eval {
+                               
$koha_spsuggest_dbh=DBI->connect("DBI:mysql:suggest:66.213.78.76","auth","Free2cirC");
+                       };
+                       if ($@) { warn "can't connect to spsuggest db";
+                       }
+                       else {
+                               my $koha_spsuggest_insert = "INSERT INTO 
phrase_log(phr_phrase,phr_resultcount,phr_ip) VALUES(?,?,?)";
+                               my $koha_spsuggest_query = "SELECT display FROM 
distincts WHERE strcmp(soundex(suggestion), soundex(?)) = 0 order by 
soundex(suggestion) limit 0,5";
+                               my $koha_spsuggest_sth = 
$koha_spsuggest_dbh->prepare($koha_spsuggest_query);
+                               $koha_spsuggest_sth->execute($phrases);
+                               while (my $spsuggestion = 
$koha_spsuggest_sth->fetchrow_array) {
+                                       $spsuggestion =~ s/(:|\/)//g;
+                                       my %line;
+                                       $line{spsuggestion} = $spsuggestion;
+                                       push @koha_spsuggest,\%line;
+                                       $koha_spsuggest = 1;
+                               }
+
+                               # Now save the current query
+                               
$koha_spsuggest_sth=$koha_spsuggest_dbh->prepare($koha_spsuggest_insert);
+                               
#$koha_spsuggest_sth->execute($phrases,$count,$ipaddress);
+                               $koha_spsuggest_sth->finish;
+
+                               $template->param( koha_spsuggest => 
$koha_spsuggest ) unless $num;
+                               $template->param( SPELL_SUGGEST => 
address@hidden,
+                                               branchloop=>address@hidden,
+                                                       
itemtypeloop=>address@hidden,
+                               );
+                       }
+               };
+               if ($@) {
+                       warn "Kohaspsuggest failure:".$@;
+               }
+       }
+       
+       ## Spellchecking using Google API
+       ## Did you mean? Suggestions using spsuggest table
+       #       
+       # Related Searches
+       #
+## OK, we're not searching, load the search template
+} else {
+
+       ($template, $borrowernumber, $cookie)
+        = get_template_and_user({template_name => "opac-zoomsearch.tmpl",
+                    query => $query,
+                    type => "opac",
+                    authnotrequired => 1,
+                });
+
+       # set the default tab, etc.
+       my $search_type = $query->param('query_form');
+       if ((!$search_type) || ($search_type eq 'advanced'))  {
+               $template->param(advanced_search => 1);
+       } elsif ($search_type eq 'format') {
+               $template->param(format_search => 1);
+       } elsif ($search_type eq 'power') {
+               $template->param(power_search => 1);
+       } elsif ($search_type eq 'cql') {
+               $template->param(power_search => 1);
+       } elsif ($search_type eq 'pqf') {
+               $template->param(power_search => 1);
+       } elsif ($search_type eq 'proximity') {
+               $template->param(proximity_search => 1);
+       }
+
+       $template->param(
+               branchloop=>address@hidden,
+               itemtypeloop=>address@hidden,
+       );
+
+}
+output_html_with_http_headers $query, $cookie, $template->output;
+
+=head2 cgi2pdf
+=cut
+# build a valid PQF query from a CGI form
+sub cgi2pqf {
+       my ($query) = @_;
+       my $nice_query; # just a string storing a nicely formatted query
+       my @default_attributes = ('sort_by');
+       # attributes specific to the advanced search - a search_point is 
actually a combination of
+       #  several bib1 attributes
+       my @advanced_attributes = ('search_point','op','query');
+       # attributes specific to the power search
+       my @power_attributes = ( 
'use','relation','structure','truncation','completeness','op','query');
+       # attributes specific to the proximity search
+       my @proximity_attributes = 
('prox_op','prox_exclusion','prox_distance','prox_ordered','prox_relation','prox_which-code','prox_unit-code','query');
+
+       my @specific_attributes; # these will be looped as many times as needed
+
+       my $query_form = $query->param('query_form');
+
+       # bunch of places to store the various queries we're working with
+       my $cql_query = $query->param('cql_query');
+
+       my $pqf_query = $query->param('pqf_query');
+
+       my @pqf_query_array;
+       my @counting_pqf_query_array;
+       
+       my $pqf_prox_ops = $query->param('pqf_prox_ops');
+       my @pqf_prox_ops_array;
+       
+       my $pqf_bool_ops = $query->param('pqf_bool_ops');
+       my @pqf_bool_ops_array;
+
+       my $pqf_sort_by = $query->param('pqf_sort_by');
+
+       # operators:
+
+       # ADVANCED SEARCH
+       if (($query_form) eq 'advanced') {
+               @specific_attributes = @advanced_attributes;
+       # POWER SEARCH
+       } elsif (($query_form) eq 'power') {
+               @specific_attributes = @power_attributes;
+       # PROXIMITY SEARCH
+       } elsif (($query_form) eq 'proximity') {
+               @specific_attributes = @proximity_attributes;
+       }
+       
+
+       # load the default attributes, set once per query
+       foreach my $def_attr (@default_attributes) {
+               $pqf_sort_by .= " ".$query->param($def_attr);
+       }
+       # these are attributes specific to this query_form, set many times per 
query
+       # First, process the 'operators' and put them in an array
+       # proximity and boolean
+       foreach my $spec_attr (@specific_attributes) {
+               for (my $i=1;$i<15;$i++) {
+                       if ($query->param("query$i")) { # make sure this set 
should be used
+                               if ($spec_attr =~ /^op/) { # process the 
operators separately
+                                       push @pqf_bool_ops_array, 
$query->param("$spec_attr$i");
+                                       $nice_query .=" 
".$query->param("$spec_attr$i")." ".$query->param("query$i");
+                                       $nice_query =~ s/address@hidden/AND/g;
+                                       $nice_query =~ s/address@hidden/OR/g;
+                               } elsif ($spec_attr =~ /^prox/) { # process the 
proximity operators separately
+                                       if ($query->param("$spec_attr$i")) {
+                                               #warn 
"PQF:".$query->param("$spec_attr$i");
+                                               push 
@pqf_prox_ops_array,$query->param("$spec_attr$i");
+                                       } else {
+                                               if (($spec_attr =~ 
/^prox_exclusion/) || ($spec_attr =~ /^prox_ordered/)) { # this is an 
exception, sloppy way to handle it
+                                                       if ($i==2) {
+                                                               push 
@pqf_prox_ops_array,0;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       # by now, we have two operator arrays: @pqf_bool_ops_array (boolean) 
and @pqf_prox_ops_array (proximity)
+
+       # Next, we process the attributes (operands)
+       for (my $i=1;$i<15;$i++) {
+               foreach my $spec_attr (@specific_attributes) {
+                       if ($query->param("query$i")) {
+                               if ($spec_attr =~ /^query/) {
+                                       push 
@counting_pqf_query_array,$query->param("$spec_attr$i") if 
$query->param("$spec_attr$i");
+                                       push 
@pqf_query_array,$query->param("$spec_attr$i") if $query->param("$spec_attr$i")
+                               } elsif ($spec_attr =~ /^op/) { # don't process 
the operators again
+                               } elsif ($spec_attr =~ /^prox/) { 
+                               } else {
+                                       push 
@pqf_query_array,$query->param("$spec_attr$i") if $query->param("$spec_attr$i");
+                               }
+                       }
+               }
+       }
+
+       # we have to make sure that there # of operators == # of operands-1
+       # because second, third, etc queries, come in with an operator attached
+       # ...but if there is no previous queries, it should be dropped ... 
+       # that's what we're doing here
+       my $count_pqf_query = @counting_pqf_query_array;
+       my $count_pqf_bool_ops = @pqf_bool_ops_array;
+
+       if ($count_pqf_bool_ops == $count_pqf_query-1) {
+               for (my $i=$count_pqf_query;$i>=0;$i--) {
+                       $pqf_bool_ops.=" ".$pqf_bool_ops_array[$i];
+               }
+       } else {
+               for (my $i=$count_pqf_query;$i>=1;$i--) {
+                       $pqf_bool_ops.=" ".$pqf_bool_ops_array[$i];
+               }
+       }
+       foreach my $que(@pqf_query_array) {
+               if ($que =~ /@/) {
+                       $pqf_query .=" ".$que;
+               } else {
+                       $que =~ s/(\"|\'|\.)//g;
+                       $pqf_query .=" \"".$que."\"";
+               }
+       }
+       foreach my $prox(@pqf_prox_ops_array) {
+               $pqf_prox_ops.=" ".$prox;
+       }
+
+       # finally, nice_query needs to be populated if it hasn't been
+       $nice_query = $pqf_query unless $nice_query;
+       # and cleaned up FIXME: bad bad ... 
+       $nice_query =~ s/address@hidden//g;
+       $nice_query =~ s/\d+=\d+//g;
+       # OK, done with that, now lets have a look
+       #warn "Boolean Operators: ".$pqf_bool_ops if $pqf_bool_ops;
+       #warn "Proximigy Operators: ".$pqf_prox_ops if $pqf_prox_ops;
+       #warn "Sort by: ".$pqf_sort_by;
+       #warn "PQF:".$pqf_query;        
+       #warn "Full PQF: $pqf_sort_by $pqf_prox_ops $pqf_bool_ops $pqf_query";
+       #warn "NICE: $nice_query";
+       return ('',$pqf_sort_by, $pqf_prox_ops, $pqf_bool_ops, $pqf_query, 
$nice_query);
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]