Bug 23763: Create a pagination_bar routine
[koha.git] / Koha / SearchEngine / Search.pm
1 package Koha::SearchEngine::Search;
2
3 # This file is part of Koha.
4 #
5 # Copyright 2015 Catalyst IT
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 # This is a shim that gives you the appropriate search object for your
21 # system preference.
22
23 =head1 NAME
24
25 Koha::SearchEngine::Search - instantiate the search object that corresponds to
26 the C<SearchEngine> system preference.
27
28 =head1 DESCRIPTION
29
30 This allows you to be agnostic about what the search engine configuration is
31 and just get whatever search object you need.
32
33 =head1 SYNOPSIS
34
35     use Koha::SearchEngine::Search;
36     my $searcher = Koha::SearchEngine::Search->new();
37
38 =head1 METHODS
39
40 =head2 new
41
42 Creates a new C<Search> of whatever the relevant type is.
43
44 =cut
45
46 use Modern::Perl;
47 use C4::Context;
48 use C4::Biblio qw//;
49 use POSIX qw(ceil floor);
50
51 sub new {
52     my $engine = C4::Context->preference("SearchEngine") // 'Zebra';
53     my $file = "Koha/SearchEngine/${engine}/Search.pm";
54     my $class = "Koha::SearchEngine::${engine}::Search";
55     require $file;
56     shift @_;
57     return $class->new(@_);
58 }
59
60 =head2 extract_biblionumber
61
62     my $biblionumber = $searcher->extract_biblionumber( $marc );
63
64 Returns the biblionumber from $marc. The routine is called from the
65 extract_biblionumber method of the specific search engine.
66
67 =cut
68
69 sub extract_biblionumber {
70     my ( $record ) = @_;
71     return if ref($record) ne 'MARC::Record';
72     my ( $biblionumbertagfield, $biblionumbertagsubfield ) = C4::Biblio::GetMarcFromKohaField( 'biblio.biblionumber' );
73     if( $biblionumbertagfield < 10 ) {
74         my $controlfield = $record->field( $biblionumbertagfield );
75         return $controlfield ? $controlfield->data : undef;
76     }
77     return $record->subfield( $biblionumbertagfield, $biblionumbertagsubfield );
78 }
79
80 =head2 pagination_bar
81
82 my ( $PAGE_NUMBERS, $hits_to_paginate, $pages, $current_page_number,
83     $previous_page_offset, $next_page_offset, $last_page_offset ) = Koha::SearchEngine::Search->pagination_bar(
84     {
85         hits              => $hits,
86         max_result_window => $max_result_window,
87         results_per_page  => $results_per_page,
88         offset            => $offset,
89         sort_by           => \@sort_by
90     }
91   );
92
93 Returns the variables needed for the page-nubers.inc to build search results
94
95 =cut
96
97 sub pagination_bar {
98     my ( $self, $params ) = @_;
99     my $hits             = $params->{hits};
100     my $results_per_page = $params->{results_per_page};
101     my $offset           = $params->{offset};
102     my $sort_by          = $params->{sort_by};
103     my @page_numbers;
104     my $max_result_window = $params->{max_result_window};
105     my $hits_to_paginate =
106       ( $max_result_window && $max_result_window < $hits )
107       ? $max_result_window
108       : $hits;
109
110     # total number of pages there will be
111     my $pages            = ceil( $hits_to_paginate / $results_per_page );
112     my $last_page_offset = ( $pages - 1 ) * $results_per_page;
113
114     # default page number
115     my $current_page_number = 1;
116     $current_page_number = ( $offset / $results_per_page + 1 ) if $offset;
117     my $previous_page_offset;
118     if ( $offset >= $results_per_page ) {
119         $previous_page_offset = $offset - $results_per_page;
120     }
121     my $next_page_offset = $offset + $results_per_page;
122
123     # If we're within the first 10 pages, keep it simple
124     if ( $current_page_number < 10 ) {
125
126         # just show the first 10 pages
127         # Loop through the pages
128         my $pages_to_show = 10;
129         $pages_to_show = $pages if $pages < 10;
130         for ( my $i = 1 ; $i <= $pages_to_show ; $i++ ) {
131
132             # the offset for this page
133             my $this_offset =
134               ( ( $i * $results_per_page ) - $results_per_page );
135
136             # the page number for this page
137             my $this_page_number = $i;
138
139             # put it in the array
140             push @page_numbers, {
141                 offset => $this_offset,
142                 pg     => $this_page_number,
143
144                 # it should only be highlighted if it's the current page
145                 highlight => $this_page_number == $current_page_number,
146                 sort_by   => join ' ',
147                 @$sort_by
148             };
149         }
150     }
151
152     # now, show up to twenty pages, with the current one smack in the middle
153     # near the end of search results we will show 10 below and as many remaining above
154     else {
155         for (
156             my $i = $current_page_number ;
157             $i <= ( $current_page_number + 19 ) ;
158             $i++
159           )
160         {
161             my $this_offset =
162               ( ( ( $i - 9 ) * $results_per_page ) - $results_per_page );
163             my $this_page_number = $i - 9;
164             if ( $this_page_number <= $pages ) {
165                 push @page_numbers,
166                   {
167                     offset    => $this_offset,
168                     pg        => $this_page_number,
169                     highlight => $this_page_number == $current_page_number,
170                     sort_by   => join ' ',
171                     @$sort_by
172                   };
173             }
174         }
175     }
176
177     return ( \@page_numbers, $hits_to_paginate, $pages, $current_page_number,
178         $previous_page_offset, $next_page_offset, $last_page_offset );
179
180 }
181
182 1;