Merge branch 'bug_8419' into 3.14-master
[koha.git] / C4 / Output.pm
blob63acf1453e01949b5d5976d0215ec05b5d3c585e
1 package C4::Output;
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
7 # Copyright 2000-2002 Katipo Communications
9 # This file is part of Koha.
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.
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.
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.
25 # NOTE: I'm pretty sure this module is deprecated in favor of
26 # templates.
28 use strict;
29 #use warnings; FIXME - Bug 2505
31 use URI::Escape;
33 use C4::Context;
34 use C4::Dates qw(format_date);
35 use C4::Budgets qw(GetCurrency);
36 use C4::Templates;
38 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
40 BEGIN {
41 # set the version for version checking
42 $VERSION = 3.07.00.049;
43 require Exporter;
45 @ISA = qw(Exporter);
46 @EXPORT_OK = qw(&is_ajax ajax_fail); # More stuff should go here instead
47 %EXPORT_TAGS = ( all =>[qw(setlanguagecookie pagination_bar parametrized_url
48 &output_with_http_headers &output_ajax_with_http_headers &output_html_with_http_headers)],
49 ajax =>[qw(&output_with_http_headers &output_ajax_with_http_headers is_ajax)],
50 html =>[qw(&output_with_http_headers &output_html_with_http_headers)]
52 push @EXPORT, qw(
53 setlanguagecookie getlanguagecookie pagination_bar parametrized_url
55 push @EXPORT, qw(
56 &output_html_with_http_headers &output_ajax_with_http_headers &output_with_http_headers FormatData FormatNumber
61 =head1 NAME
63 C4::Output - Functions for managing output, is slowly being deprecated
65 =head1 FUNCTIONS
67 =over 2
68 =cut
70 =item FormatNumber
71 =cut
72 sub FormatNumber{
73 my $cur = GetCurrency;
74 my $cur_format = C4::Context->preference("CurrencyFormat");
75 my $num;
77 if ( $cur_format eq 'FR' ) {
78 $num = new Number::Format(
79 'decimal_fill' => '2',
80 'decimal_point' => ',',
81 'int_curr_symbol' => $cur->{symbol},
82 'mon_thousands_sep' => ' ',
83 'thousands_sep' => ' ',
84 'mon_decimal_point' => ','
86 } else { # US by default..
87 $num = new Number::Format(
88 'int_curr_symbol' => '',
89 'mon_thousands_sep' => ',',
90 'mon_decimal_point' => '.'
93 return $num;
96 =item FormatData
98 FormatData($data_hashref)
99 C<$data_hashref> is a ref to data to format
101 Format dates of data those dates are assumed to contain date in their noun
102 Could be used in order to centralize all the formatting for HTML output
103 =cut
105 sub FormatData{
106 my $data_hashref=shift;
107 $$data_hashref{$_} = format_date( $$data_hashref{$_} ) for grep{/date/} keys (%$data_hashref);
110 =item pagination_bar
112 pagination_bar($base_url, $nb_pages, $current_page, $startfrom_name)
114 Build an HTML pagination bar based on the number of page to display, the
115 current page and the url to give to each page link.
117 C<$base_url> is the URL for each page link. The
118 C<$startfrom_name>=page_number is added at the end of the each URL.
120 C<$nb_pages> is the total number of pages available.
122 C<$current_page> is the current page number. This page number won't become a
123 link.
125 This function returns HTML, without any language dependency.
127 =cut
129 sub pagination_bar {
130 my $base_url = (@_ ? shift : $ENV{SCRIPT_NAME} . $ENV{QUERY_STRING}) or return;
131 my $nb_pages = (@_) ? shift : 1;
132 my $current_page = (@_) ? shift : undef; # delay default until later
133 my $startfrom_name = (@_) ? shift : 'page';
135 # how many pages to show before and after the current page?
136 my $pages_around = 2;
138 my $delim = qr/\&(?:amp;)?|;/; # "non memory" cluster: no backreference
139 $base_url =~ s/$delim*\b$startfrom_name=(\d+)//g; # remove previous pagination var
140 unless (defined $current_page and $current_page > 0 and $current_page <= $nb_pages) {
141 $current_page = ($1) ? $1 : 1; # pull current page from param in URL, else default to 1
142 # $debug and # FIXME: use C4::Debug;
143 # warn "with QUERY_STRING:" .$ENV{QUERY_STRING}. "\ncurrent_page:$current_page\n1:$1 2:$2 3:$3";
145 $base_url =~ s/($delim)+/$1/g; # compress duplicate delims
146 $base_url =~ s/$delim;//g; # remove empties
147 $base_url =~ s/$delim$//; # remove trailing delim
149 my $url = $base_url . (($base_url =~ m/$delim/ or $base_url =~ m/\?/) ? '&amp;' : '?' ) . $startfrom_name . '=';
150 my $pagination_bar = '';
152 # navigation bar useful only if more than one page to display !
153 if ( $nb_pages > 1 ) {
155 # link to first page?
156 if ( $current_page > 1 ) {
157 $pagination_bar .=
158 "\n" . '&nbsp;'
159 . '<a href="'
160 . $url
161 . '1" rel="start">'
162 . '&lt;&lt;' . '</a>';
164 else {
165 $pagination_bar .=
166 "\n" . '&nbsp;<span class="inactive">&lt;&lt;</span>';
169 # link on previous page ?
170 if ( $current_page > 1 ) {
171 my $previous = $current_page - 1;
173 $pagination_bar .=
174 "\n" . '&nbsp;'
175 . '<a href="'
176 . $url
177 . $previous
178 . '" rel="prev">' . '&lt;' . '</a>';
180 else {
181 $pagination_bar .=
182 "\n" . '&nbsp;<span class="inactive">&lt;</span>';
185 my $min_to_display = $current_page - $pages_around;
186 my $max_to_display = $current_page + $pages_around;
187 my $last_displayed_page = undef;
189 for my $page_number ( 1 .. $nb_pages ) {
190 if (
191 $page_number == 1
192 or $page_number == $nb_pages
193 or ( $page_number >= $min_to_display
194 and $page_number <= $max_to_display )
197 if ( defined $last_displayed_page
198 and $last_displayed_page != $page_number - 1 )
200 $pagination_bar .=
201 "\n" . '&nbsp;<span class="inactive">...</span>';
204 if ( $page_number == $current_page ) {
205 $pagination_bar .=
206 "\n" . '&nbsp;'
207 . '<span class="currentPage">'
208 . $page_number
209 . '</span>';
211 else {
212 $pagination_bar .=
213 "\n" . '&nbsp;'
214 . '<a href="'
215 . $url
216 . $page_number . '">'
217 . $page_number . '</a>';
219 $last_displayed_page = $page_number;
223 # link on next page?
224 if ( $current_page < $nb_pages ) {
225 my $next = $current_page + 1;
227 $pagination_bar .= "\n"
228 . '&nbsp;<a href="'
229 . $url
230 . $next
231 . '" rel="next">' . '&gt;' . '</a>';
233 else {
234 $pagination_bar .=
235 "\n" . '&nbsp;<span class="inactive">&gt;</span>';
238 # link to last page?
239 if ( $current_page != $nb_pages ) {
240 $pagination_bar .= "\n"
241 . '&nbsp;<a href="'
242 . $url
243 . $nb_pages
244 . '" rel="last">'
245 . '&gt;&gt;' . '</a>';
247 else {
248 $pagination_bar .=
249 "\n" . '&nbsp;<span class="inactive">&gt;&gt;</span>';
253 return $pagination_bar;
256 =item output_with_http_headers
258 &output_with_http_headers($query, $cookie, $data, $content_type[, $status])
260 Outputs $data with the appropriate HTTP headers,
261 the authentication cookie $cookie and a Content-Type specified in
262 $content_type.
264 If applicable, $cookie can be undef, and it will not be sent.
266 $content_type is one of the following: 'html', 'js', 'json', 'xml', 'rss', or 'atom'.
268 $status is an HTTP status message, like '403 Authentication Required'. It defaults to '200 OK'.
270 =cut
272 sub output_with_http_headers {
273 my ( $query, $cookie, $data, $content_type, $status ) = @_;
274 $status ||= '200 OK';
276 my %content_type_map = (
277 'html' => 'text/html',
278 'js' => 'text/javascript',
279 'json' => 'application/json',
280 'xml' => 'text/xml',
281 # NOTE: not using application/atom+xml or application/rss+xml because of
282 # Internet Explorer 6; see bug 2078.
283 'rss' => 'text/xml',
284 'atom' => 'text/xml'
287 die "Unknown content type '$content_type'" if ( !defined( $content_type_map{$content_type} ) );
288 my $options = {
289 type => $content_type_map{$content_type},
290 status => $status,
291 charset => 'UTF-8',
292 Pragma => 'no-cache',
293 'Cache-Control' => 'no-cache',
295 $options->{cookie} = $cookie if $cookie;
296 if ($content_type eq 'html') { # guaranteed to be one of the content_type_map keys, else we'd have died
297 $options->{'Content-Style-Type' } = 'text/css';
298 $options->{'Content-Script-Type'} = 'text/javascript';
301 $data =~ s/\&amp\;amp\; /\&amp\; /g;
302 utf8::encode($data);
303 print $query->header($options), $data;
306 sub output_html_with_http_headers {
307 my ( $query, $cookie, $data, $status ) = @_;
308 output_with_http_headers( $query, $cookie, $data, 'html', $status );
312 sub output_ajax_with_http_headers {
313 my ( $query, $js ) = @_;
314 print $query->header(
315 -type => 'text/javascript',
316 -charset => 'UTF-8',
317 -Pragma => 'no-cache',
318 -'Cache-Control' => 'no-cache',
319 -expires => '-1d',
320 ), $js;
323 sub is_ajax {
324 my $x_req = $ENV{HTTP_X_REQUESTED_WITH};
325 return ( $x_req and $x_req =~ /XMLHttpRequest/i ) ? 1 : 0;
328 sub parametrized_url {
329 my $url = shift || ''; # ie page.pl?ln={LANG}
330 my $vars = shift || {}; # ie { LANG => en }
331 my $ret = $url;
332 while ( my ($key,$val) = each %$vars) {
333 my $val_url = URI::Escape::uri_escape_utf8($val);
334 $ret =~ s/\{$key\}/$val_url/g;
336 $ret =~ s/\{[^\{]*\}//g; # remove not defined vars
337 return $ret;
340 END { } # module clean-up code here (global destructor)
343 __END__
345 =back
347 =head1 AUTHOR
349 Koha Development Team <http://koha-community.org/>
351 =cut