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