fix for 1754; fixing I18N BiDi, improvements to handling of language
[koha.git] / C4 / Output.pm
1 package C4::Output;
2
3 #package to deal with marking up output
4 #You will need to edit parts of this pm
5 #set the value of path to be where your html lives
6
7 # Copyright 2000-2002 Katipo Communications
8 #
9 # This file is part of Koha.
10 #
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 #
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
22 # Suite 330, Boston, MA  02111-1307 USA
23
24
25 # NOTE: I'm pretty sure this module is deprecated in favor of
26 # templates.
27
28 use strict;
29
30 use C4::Context;
31 use C4::Languages qw(getTranslatedLanguages get_bidi regex_lang_subtags language_get_description accept_language );
32
33 use HTML::Template::Pro;
34 use vars qw($VERSION @ISA @EXPORT);
35
36 BEGIN {
37     # set the version for version checking
38     $VERSION = 3.01;
39     require Exporter;
40     @ISA    = qw(Exporter);
41     push @EXPORT, qw(
42         &themelanguage &gettemplate setlanguagecookie pagination_bar
43     );
44     push @EXPORT, qw(
45         &output_html_with_http_headers
46     );
47 }
48
49 =head1 NAME
50
51 C4::Output - Functions for managing templates
52
53 =head1 FUNCTIONS
54
55 =over 2
56
57 =cut
58
59 #FIXME: this is a quick fix to stop rc1 installing broken
60 #Still trying to figure out the correct fix.
61 my $path = C4::Context->config('intrahtdocs') . "/prog/en/includes/";
62
63 #---------------------------------------------------------------------------------------------------------
64 # FIXME - POD
65 sub gettemplate {
66     my ( $tmplbase, $interface, $query ) = @_;
67     ($query) or warn "no query in gettemplate";
68     my $htdocs;
69     if ( $interface ne "intranet" ) {
70         $htdocs = C4::Context->config('opachtdocs');
71     }
72     else {
73         $htdocs = C4::Context->config('intrahtdocs');
74     }
75     my $path = C4::Context->preference('intranet_includes') || 'includes';
76
77     my ( $theme, $lang ) = themelanguage( $htdocs, $tmplbase, $interface, $query );
78     my $opacstylesheet = C4::Context->preference('opacstylesheet');
79
80     # if the template doesn't exist, load the English one as a last resort
81     my $filename = "$htdocs/$theme/$lang/modules/$tmplbase";
82     unless (-f $filename) {
83         $lang = 'en';
84         $filename = "$htdocs/$theme/$lang/".($interface eq 'intranet'?"modules":"")."/$tmplbase";
85     }
86     my $template       = HTML::Template::Pro->new(
87         filename          => $filename,
88         die_on_bad_params => 1,
89         global_vars       => 1,
90         case_sensitive    => 1,
91         path              => ["$htdocs/$theme/$lang/$path"]
92     );
93
94     $template->param(
95         themelang => ( $interface ne 'intranet' ? '/opac-tmpl' : '/intranet-tmpl' )
96           . "/$theme/$lang",
97         interface => ( $interface ne 'intranet' ? '/opac-tmpl' : '/intranet-tmpl' ),
98         theme => $theme,
99         opacstylesheet      => $opacstylesheet,
100         opaccolorstylesheet => C4::Context->preference('opaccolorstylesheet'),
101         opacsmallimage      => C4::Context->preference('opacsmallimage'),
102         lang                => $lang
103     );
104
105     # Bidirectionality
106     my $current_lang = regex_lang_subtags($lang);
107     my $bidi;
108     $bidi = get_bidi($current_lang->{script}) if $current_lang->{script};
109     # Languages
110     my $languages_loop = getTranslatedLanguages($interface,$theme,$lang);
111     $template->param(
112             languages_loop => $languages_loop,
113             bidi => $bidi
114     ) unless @$languages_loop<2;
115
116     return $template;
117 }
118
119 #---------------------------------------------------------------------------------------------------------
120 # FIXME - POD
121 sub themelanguage {
122     my ( $htdocs, $tmpl, $interface, $query ) = @_;
123     ($query) or warn "no query in themelanguage";
124
125     # Set some defaults for language and theme
126     # First, check the user's preferences
127     my $lang;
128     my $http_accept_language = regex_lang_subtags($ENV{HTTP_ACCEPT_LANGUAGE})->{language};
129     if ($http_accept_language) {
130         $lang = accept_language($http_accept_language,getTranslatedLanguages($interface,'prog'));
131     } 
132     # But, if there's a cookie set, obey it
133     $lang = $query->cookie('KohaOpacLanguage') if $query->cookie('KohaOpacLanguage');
134     # Fall back to English
135     $lang = 'en' unless $lang;
136     my $theme = 'prog';
137
138     my $dbh = C4::Context->dbh;
139     my @languages;
140     my @themes;
141     if ( $interface eq "intranet" ) {
142         @languages = split " ", C4::Context->preference("opaclanguages");
143         @themes    = split " ", C4::Context->preference("template");
144         @languages = ($lang,@languages) if $lang;
145     }
146     else {
147       # we are in the opac here, what im trying to do is let the individual user
148       # set the theme they want to use.
149       # and perhaps the them as well.
150         #my $lang = $query->cookie('KohaOpacLanguage');
151         if ($lang) {                        # FIXME: if $lang always TRUE!
152             push @languages, $lang;
153         }
154         else {
155             @languages = split " ", C4::Context->preference("opaclanguages");
156         }
157         @themes = split " ", C4::Context->preference("opacthemes");
158     }
159
160  # searches through the themes and languages. First template it find it returns.
161  # Priority is for getting the theme right.
162     THEME:
163     foreach my $th (@themes) {
164         foreach my $la (@languages) {
165             #for ( my $pass = 1 ; $pass <= 2 ; $pass += 1 ) {
166                 warn "$htdocs/$th/$la/modules/$interface-"."tmpl";
167                 #$la =~ s/([-_])/ $1 eq '-'? '_': '-' /eg if $pass == 2;
168                 if ( -e "$htdocs/$th/$la/modules/$interface-"."tmpl") {
169                 #".($interface eq 'intranet'?"modules":"")."/$tmpl" ) {
170                     $theme = $th;
171                     $lang  = $la;
172                     last THEME;
173                 }
174                 last unless $la =~ /[-_]/;
175             #}
176         }
177     }
178     return ( $theme, $lang );
179 }
180
181 sub setlanguagecookie {
182     my ( $query, $language, $uri ) = @_;
183     my $cookie = $query->cookie(
184         -name    => 'KohaOpacLanguage',
185         -value   => $language,
186         -expires => ''
187     );
188     print $query->redirect(
189         -uri    => $uri,
190         -cookie => $cookie
191     );
192 }
193
194 =item pagination_bar
195
196    pagination_bar($base_url, $nb_pages, $current_page, $startfrom_name)
197
198 Build an HTML pagination bar based on the number of page to display, the
199 current page and the url to give to each page link.
200
201 C<$base_url> is the URL for each page link. The
202 C<$startfrom_name>=page_number is added at the end of the each URL.
203
204 C<$nb_pages> is the total number of pages available.
205
206 C<$current_page> is the current page number. This page number won't become a
207 link.
208
209 This function returns HTML, without any language dependency.
210
211 =cut
212
213 sub pagination_bar {
214     my ( $base_url, $nb_pages, $current_page, $startfrom_name ) = @_;
215
216     # how many pages to show before and after the current page?
217     my $pages_around = 2;
218
219     my $url =
220       $base_url . ( $base_url =~ m/&/ ? '&amp;' : '?' ) . $startfrom_name . '=';
221
222     my $pagination_bar = '';
223
224     # current page detection
225     if ( not defined $current_page ) {
226         $current_page = 1;
227     }
228
229     # navigation bar useful only if more than one page to display !
230     if ( $nb_pages > 1 ) {
231
232         # link to first page?
233         if ( $current_page > 1 ) {
234             $pagination_bar .=
235                 "\n" . '&nbsp;'
236               . '<a href="'
237               . $url
238               . '1" rel="start">'
239               . '&lt;&lt;' . '</a>';
240         }
241         else {
242             $pagination_bar .=
243               "\n" . '&nbsp;<span class="inactive">&lt;&lt;</span>';
244         }
245
246         # link on previous page ?
247         if ( $current_page > 1 ) {
248             my $previous = $current_page - 1;
249
250             $pagination_bar .=
251                 "\n" . '&nbsp;'
252               . '<a href="'
253               . $url
254               . $previous
255               . '" rel="prev">' . '&lt;' . '</a>';
256         }
257         else {
258             $pagination_bar .=
259               "\n" . '&nbsp;<span class="inactive">&lt;</span>';
260         }
261
262         my $min_to_display      = $current_page - $pages_around;
263         my $max_to_display      = $current_page + $pages_around;
264         my $last_displayed_page = undef;
265
266         for my $page_number ( 1 .. $nb_pages ) {
267             if (
268                    $page_number == 1
269                 or $page_number == $nb_pages
270                 or (    $page_number >= $min_to_display
271                     and $page_number <= $max_to_display )
272               )
273             {
274                 if ( defined $last_displayed_page
275                     and $last_displayed_page != $page_number - 1 )
276                 {
277                     $pagination_bar .=
278                       "\n" . '&nbsp;<span class="inactive">...</span>';
279                 }
280
281                 if ( $page_number == $current_page ) {
282                     $pagination_bar .=
283                         "\n" . '&nbsp;'
284                       . '<span class="currentPage">'
285                       . $page_number
286                       . '</span>';
287                 }
288                 else {
289                     $pagination_bar .=
290                         "\n" . '&nbsp;'
291                       . '<a href="'
292                       . $url
293                       . $page_number . '">'
294                       . $page_number . '</a>';
295                 }
296                 $last_displayed_page = $page_number;
297             }
298         }
299
300         # link on next page?
301         if ( $current_page < $nb_pages ) {
302             my $next = $current_page + 1;
303
304             $pagination_bar .= "\n"
305               . '&nbsp;<a href="'
306               . $url
307               . $next
308               . '" rel="next">' . '&gt;' . '</a>';
309         }
310         else {
311             $pagination_bar .=
312               "\n" . '&nbsp;<span class="inactive">&gt;</span>';
313         }
314
315         # link to last page?
316         if ( $current_page != $nb_pages ) {
317             $pagination_bar .= "\n"
318               . '&nbsp;<a href="'
319               . $url
320               . $nb_pages
321               . '" rel="last">'
322               . '&gt;&gt;' . '</a>';
323         }
324         else {
325             $pagination_bar .=
326               "\n" . '&nbsp;<span class="inactive">&gt;&gt;</span>';
327         }
328     }
329
330     return $pagination_bar;
331 }
332
333 =item output_html_with_http_headers
334
335    &output_html_with_http_headers($query, $cookie, $html)
336
337 Outputs the HTML page $html with the appropriate HTTP headers,
338 with the authentication cookie $cookie and a Content-Type that
339 corresponds to the HTML page $html.
340
341 =cut
342
343 sub output_html_with_http_headers ($$$) {
344     my($query, $cookie, $html) = @_;
345     print $query->header(
346         -type    => 'text/html',
347         -charset => 'UTF-8',
348         -cookie  => $cookie,
349         -Pragma => 'no-cache',
350         -'Cache-Control' => 'no-cache',
351     ), $html;
352 }
353
354 END { }    # module clean-up code here (global destructor)
355
356 1;
357 __END__
358
359 =back
360
361 =head1 AUTHOR
362
363 Koha Developement team <info@koha.org>
364
365 =cut