Bug 6755 Problems with switching languages
[koha-ffzg.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
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24
25 # NOTE: I'm pretty sure this module is deprecated in favor of
26 # templates.
27
28 use strict;
29 #use warnings; FIXME - Bug 2505
30
31 use C4::Context;
32 use C4::Dates qw(format_date);
33 use C4::Budgets qw(GetCurrency);
34 use C4::Templates;
35
36 #use HTML::Template::Pro;
37 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
38
39 BEGIN {
40     # set the version for version checking
41     $VERSION = 3.03;
42     require Exporter;
43     @ISA    = qw(Exporter);
44         @EXPORT_OK = qw(&is_ajax ajax_fail); # More stuff should go here instead
45         %EXPORT_TAGS = ( all =>[qw(&pagination_bar
46                                                            &output_with_http_headers &output_html_with_http_headers)],
47                                         ajax =>[qw(&output_with_http_headers is_ajax)],
48                                         html =>[qw(&output_with_http_headers &output_html_with_http_headers)]
49                                 );
50     push @EXPORT, qw(
51         &output_html_with_http_headers &output_with_http_headers FormatData FormatNumber pagination_bar
52     );
53 }
54
55
56 =item FormatNumber
57 =cut
58 sub FormatNumber{
59 my $cur  =  GetCurrency;
60 my $cur_format = C4::Context->preference("CurrencyFormat");
61 my $num;
62
63 if ( $cur_format eq 'FR' ) {
64     $num = new Number::Format(
65         'decimal_fill'      => '2',
66         'decimal_point'     => ',',
67         'int_curr_symbol'   => $cur->{symbol},
68         'mon_thousands_sep' => ' ',
69         'thousands_sep'     => ' ',
70         'mon_decimal_point' => ','
71     );
72 } else {  # US by default..
73     $num = new Number::Format(
74         'int_curr_symbol'   => '',
75         'mon_thousands_sep' => ',',
76         'mon_decimal_point' => '.'
77     );
78 }
79 return $num;
80 }
81
82 =item FormatData
83
84 FormatData($data_hashref)
85 C<$data_hashref> is a ref to data to format
86
87 Format dates of data those dates are assumed to contain date in their noun
88 Could be used in order to centralize all the formatting for HTML output
89 =cut
90
91 sub FormatData{
92                 my $data_hashref=shift;
93         $$data_hashref{$_} = format_date( $$data_hashref{$_} ) for grep{/date/} keys (%$data_hashref);
94 }
95
96 =item pagination_bar
97
98    pagination_bar($base_url, $nb_pages, $current_page, $startfrom_name)
99
100 Build an HTML pagination bar based on the number of page to display, the
101 current page and the url to give to each page link.
102
103 C<$base_url> is the URL for each page link. The
104 C<$startfrom_name>=page_number is added at the end of the each URL.
105
106 C<$nb_pages> is the total number of pages available.
107
108 C<$current_page> is the current page number. This page number won't become a
109 link.
110
111 This function returns HTML, without any language dependency.
112
113 =cut
114
115 sub pagination_bar {
116         my $base_url = (@_ ? shift : $ENV{SCRIPT_NAME} . $ENV{QUERY_STRING}) or return undef;
117     my $nb_pages       = (@_) ? shift : 1;
118     my $current_page   = (@_) ? shift : undef;  # delay default until later
119     my $startfrom_name = (@_) ? shift : 'page';
120
121     # how many pages to show before and after the current page?
122     my $pages_around = 2;
123
124         my $delim = qr/\&(?:amp;)?|;/;          # "non memory" cluster: no backreference
125         $base_url =~ s/$delim*\b$startfrom_name=(\d+)//g; # remove previous pagination var
126     unless (defined $current_page and $current_page > 0 and $current_page <= $nb_pages) {
127         $current_page = ($1) ? $1 : 1;  # pull current page from param in URL, else default to 1
128                 # $debug and    # FIXME: use C4::Debug;
129                 # warn "with QUERY_STRING:" .$ENV{QUERY_STRING}. "\ncurrent_page:$current_page\n1:$1  2:$2  3:$3";
130     }
131         $base_url =~ s/($delim)+/$1/g;  # compress duplicate delims
132         $base_url =~ s/$delim;//g;              # remove empties
133         $base_url =~ s/$delim$//;               # remove trailing delim
134
135     my $url = $base_url . (($base_url =~ m/$delim/ or $base_url =~ m/\?/) ? '&amp;' : '?' ) . $startfrom_name . '=';
136     my $pagination_bar = '';
137
138     # navigation bar useful only if more than one page to display !
139     if ( $nb_pages > 1 ) {
140
141         # link to first page?
142         if ( $current_page > 1 ) {
143             $pagination_bar .=
144                 "\n" . '&nbsp;'
145               . '<a href="'
146               . $url
147               . '1" rel="start">'
148               . '&lt;&lt;' . '</a>';
149         }
150         else {
151             $pagination_bar .=
152               "\n" . '&nbsp;<span class="inactive">&lt;&lt;</span>';
153         }
154
155         # link on previous page ?
156         if ( $current_page > 1 ) {
157             my $previous = $current_page - 1;
158
159             $pagination_bar .=
160                 "\n" . '&nbsp;'
161               . '<a href="'
162               . $url
163               . $previous
164               . '" rel="prev">' . '&lt;' . '</a>';
165         }
166         else {
167             $pagination_bar .=
168               "\n" . '&nbsp;<span class="inactive">&lt;</span>';
169         }
170
171         my $min_to_display      = $current_page - $pages_around;
172         my $max_to_display      = $current_page + $pages_around;
173         my $last_displayed_page = undef;
174
175         for my $page_number ( 1 .. $nb_pages ) {
176             if (
177                    $page_number == 1
178                 or $page_number == $nb_pages
179                 or (    $page_number >= $min_to_display
180                     and $page_number <= $max_to_display )
181               )
182             {
183                 if ( defined $last_displayed_page
184                     and $last_displayed_page != $page_number - 1 )
185                 {
186                     $pagination_bar .=
187                       "\n" . '&nbsp;<span class="inactive">...</span>';
188                 }
189
190                 if ( $page_number == $current_page ) {
191                     $pagination_bar .=
192                         "\n" . '&nbsp;'
193                       . '<span class="currentPage">'
194                       . $page_number
195                       . '</span>';
196                 }
197                 else {
198                     $pagination_bar .=
199                         "\n" . '&nbsp;'
200                       . '<a href="'
201                       . $url
202                       . $page_number . '">'
203                       . $page_number . '</a>';
204                 }
205                 $last_displayed_page = $page_number;
206             }
207         }
208
209         # link on next page?
210         if ( $current_page < $nb_pages ) {
211             my $next = $current_page + 1;
212
213             $pagination_bar .= "\n"
214               . '&nbsp;<a href="'
215               . $url
216               . $next
217               . '" rel="next">' . '&gt;' . '</a>';
218         }
219         else {
220             $pagination_bar .=
221               "\n" . '&nbsp;<span class="inactive">&gt;</span>';
222         }
223
224         # link to last page?
225         if ( $current_page != $nb_pages ) {
226             $pagination_bar .= "\n"
227               . '&nbsp;<a href="'
228               . $url
229               . $nb_pages
230               . '" rel="last">'
231               . '&gt;&gt;' . '</a>';
232         }
233         else {
234             $pagination_bar .=
235               "\n" . '&nbsp;<span class="inactive">&gt;&gt;</span>';
236         }
237     }
238
239     return $pagination_bar;
240 }
241
242 =item output_with_http_headers
243
244    &output_with_http_headers($query, $cookie, $data, $content_type[, $status])
245
246 Outputs $data with the appropriate HTTP headers,
247 the authentication cookie $cookie and a Content-Type specified in
248 $content_type.
249
250 If applicable, $cookie can be undef, and it will not be sent.
251
252 $content_type is one of the following: 'html', 'js', 'json', 'xml', 'rss', or 'atom'.
253
254 $status is an HTTP status message, like '403 Authentication Required'. It defaults to '200 OK'.
255
256 =cut
257
258 sub output_with_http_headers($$$$;$) {
259     my ( $query, $cookie, $data, $content_type, $status ) = @_;
260     $status ||= '200 OK';
261
262     my %content_type_map = (
263         'html' => 'text/html',
264         'js'   => 'text/javascript',
265         'json' => 'application/json',
266         'xml'  => 'text/xml',
267         # NOTE: not using application/atom+xml or application/rss+xml because of
268         # Internet Explorer 6; see bug 2078.
269         'rss'  => 'text/xml',
270         'atom' => 'text/xml'
271     );
272
273     die "Unknown content type '$content_type'" if ( !defined( $content_type_map{$content_type} ) );
274     my $options = {
275         type    => $content_type_map{$content_type},
276         status  => $status,
277         charset => 'UTF-8',
278         Pragma          => 'no-cache',
279         'Cache-Control' => 'no-cache',
280     };
281     $options->{cookie} = $cookie if $cookie;
282     if ($content_type eq 'html') {  # guaranteed to be one of the content_type_map keys, else we'd have died
283         $options->{'Content-Style-Type' } = 'text/css';
284         $options->{'Content-Script-Type'} = 'text/javascript';
285     }
286     # remove SUDOC specific NSB NSE
287     $data =~ s/\x{C2}\x{98}|\x{C2}\x{9C}/ /g;
288     $data =~ s/\x{C2}\x{88}|\x{C2}\x{89}/ /g;
289       
290 # We can't encode here, that will double encode our templates, and xslt
291 # We need to fix the encoding as it comes out of the database, or when we pass the variables to templates
292  
293 #    utf8::encode($data) if utf8::is_utf8($data);
294
295     print $query->header($options), $data;
296 }
297
298 sub output_html_with_http_headers ($$$;$) {
299     my ( $query, $cookie, $data, $status ) = @_;
300     $data =~ s/\&amp\;amp\; /\&amp\; /g;
301     output_with_http_headers( $query, $cookie, $data, 'html', $status );
302 }
303
304 sub is_ajax () {
305     my $x_req = $ENV{HTTP_X_REQUESTED_WITH};
306     return ( $x_req and $x_req =~ /XMLHttpRequest/i ) ? 1 : 0;
307 }
308
309 END { }    # module clean-up code here (global destructor)
310
311 1;
312 __END__
313
314 =back
315
316 =head1 AUTHOR
317
318 Koha Development Team <http://koha-community.org/>
319
320 =cut