| File: | C4/Templates.pm |
| Coverage: | 14.8% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package C4::Templates; | |||||
| 2 | ||||||
| 3 | 2 2 2 | 41 31 76 | use strict; | |||
| 4 | 2 2 2 | 36 28 95 | use warnings; | |||
| 5 | 2 2 2 | 32 82 172 | use Carp; | |||
| 6 | 2 2 2 | 264 15402 80 | use CGI; | |||
| 7 | 2 2 2 | 178 45 186 | use List::Util qw/first/; | |||
| 8 | ||||||
| 9 | # Copyright 2009 Chris Cormack and The Koha Dev Team | |||||
| 10 | # | |||||
| 11 | # This file is part of Koha. | |||||
| 12 | # | |||||
| 13 | # Koha is free software; you can redistribute it and/or modify it under the | |||||
| 14 | # terms of the GNU General Public License as published by the Free Software | |||||
| 15 | # Foundation; either version 2 of the License, or (at your option) any later | |||||
| 16 | # version. | |||||
| 17 | # | |||||
| 18 | # Koha is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| 19 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| 20 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| 21 | # | |||||
| 22 | # You should have received a copy of the GNU General Public License along with | |||||
| 23 | # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | |||||
| 24 | # Suite 330, Boston, MA 02111-1307 USA | |||||
| 25 | ||||||
| 26 - 30 | =head1 NAME
Koha::Templates - Object for manipulating templates for use with Koha
=cut | |||||
| 31 | ||||||
| 32 | 2 2 2 | 46 25 241 | use base qw(Class::Accessor); | |||
| 33 | 2 2 2 | 2690 38188 133 | use Template; | |||
| 34 | 2 2 2 | 54 46 521 | use Template::Constants qw( :debug ); | |||
| 35 | 2 2 2 | 355 39 178 | use C4::Languages qw(getTranslatedLanguages get_bidi regex_lang_subtags language_get_description accept_language ); | |||
| 36 | ||||||
| 37 | 2 2 2 | 16 6 22 | use C4::Context; | |||
| 38 | ||||||
| 39 | __PACKAGE__->mk_accessors(qw( theme lang filename htdocs interface vars)); | |||||
| 40 | ||||||
| 41 | ||||||
| 42 | ||||||
| 43 | sub new { | |||||
| 44 | 0 | my $class = shift; | ||||
| 45 | 0 | my $interface = shift; | ||||
| 46 | 0 | my $filename = shift; | ||||
| 47 | 0 | my $tmplbase = shift; | ||||
| 48 | 0 | my $query = @_? shift: undef; | ||||
| 49 | 0 | my $htdocs; | ||||
| 50 | 0 | if ( $interface ne "intranet" ) { | ||||
| 51 | 0 | $htdocs = C4::Context->config('opachtdocs'); | ||||
| 52 | } | |||||
| 53 | else { | |||||
| 54 | 0 | $htdocs = C4::Context->config('intrahtdocs'); | ||||
| 55 | } | |||||
| 56 | 0 | my ($theme, $lang)= themelanguage( $htdocs, $tmplbase, $interface, $query); | ||||
| 57 | 0 | my $template = Template->new( | ||||
| 58 | { EVAL_PERL => 1, | |||||
| 59 | ABSOLUTE => 1, | |||||
| 60 | PLUGIN_BASE => 'Koha::Template::Plugin', | |||||
| 61 | COMPILE_EXT => C4::Context->config('template_cache_dir')?'.ttc':'', | |||||
| 62 | COMPILE_DIR => C4::Context->config('template_cache_dir')?C4::Context->config('template_cache_dir'):'',, | |||||
| 63 | INCLUDE_PATH => [ | |||||
| 64 | "$htdocs/$theme/$lang/includes", | |||||
| 65 | "$htdocs/$theme/en/includes" | |||||
| 66 | ], | |||||
| 67 | FILTERS => {}, | |||||
| 68 | } | |||||
| 69 | ) or die Template->error(); | |||||
| 70 | 0 | my $self = { | ||||
| 71 | TEMPLATE => $template, | |||||
| 72 | VARS => {}, | |||||
| 73 | }; | |||||
| 74 | 0 | bless $self, $class; | ||||
| 75 | 0 | $self->theme($theme); | ||||
| 76 | 0 | $self->lang($lang); | ||||
| 77 | 0 | $self->filename($filename); | ||||
| 78 | 0 | $self->htdocs($htdocs); | ||||
| 79 | 0 | $self->interface($interface); | ||||
| 80 | 0 | $self->{VARS}->{"test"} = "value"; | ||||
| 81 | 0 | return $self; | ||||
| 82 | ||||||
| 83 | } | |||||
| 84 | ||||||
| 85 | sub output { | |||||
| 86 | 0 | my $self = shift; | ||||
| 87 | 0 | my $vars = shift; | ||||
| 88 | ||||||
| 89 | # my $file = $self->htdocs . '/' . $self->theme .'/'.$self->lang.'/'.$self->filename; | |||||
| 90 | 0 | my $template = $self->{TEMPLATE}; | ||||
| 91 | 0 | if ( $self->interface eq 'intranet' ) { | ||||
| 92 | 0 | $vars->{themelang} = '/intranet-tmpl'; | ||||
| 93 | } | |||||
| 94 | else { | |||||
| 95 | 0 | $vars->{themelang} = '/opac-tmpl'; | ||||
| 96 | } | |||||
| 97 | 0 | $vars->{lang} = $self->lang; | ||||
| 98 | 0 | $vars->{themelang} .= '/' . $self->theme . '/' . $self->lang; | ||||
| 99 | 0 | $vars->{yuipath} = | ||||
| 100 | ( C4::Context->preference("yuipath") eq "local" | |||||
| 101 | ? $vars->{themelang} . "/lib/yui" | |||||
| 102 | : C4::Context->preference("yuipath") ); | |||||
| 103 | 0 | $vars->{interface} = | ||||
| 104 | ( $self->{interface} ne 'intranet' ? '/opac-tmpl' : '/intranet-tmpl' ); | |||||
| 105 | 0 | $vars->{theme} = $self->theme; | ||||
| 106 | 0 | $vars->{opaccolorstylesheet} = | ||||
| 107 | C4::Context->preference('opaccolorstylesheet'); | |||||
| 108 | 0 | $vars->{opacsmallimage} = C4::Context->preference('opacsmallimage'); | ||||
| 109 | 0 | $vars->{opacstylesheet} = C4::Context->preference('opacstylesheet'); | ||||
| 110 | ||||||
| 111 | # add variables set via param to $vars for processing | |||||
| 112 | # and clean any utf8 mess | |||||
| 113 | 0 0 | for my $k ( keys %{ $self->{VARS} } ) { | ||||
| 114 | 0 | $vars->{$k} = $self->{VARS}->{$k}; | ||||
| 115 | 0 | if (ref($vars->{$k}) eq 'ARRAY'){ | ||||
| 116 | 0 | utf8_arrayref($vars->{$k}); | ||||
| 117 | } | |||||
| 118 | elsif (ref($vars->{$k}) eq 'HASH'){ | |||||
| 119 | 0 | utf8_hashref($vars->{$k}); | ||||
| 120 | } | |||||
| 121 | else { | |||||
| 122 | 0 | utf8::encode($vars->{$k}) if utf8::is_utf8($vars->{$k}); | ||||
| 123 | } | |||||
| 124 | } | |||||
| 125 | 0 | my $data; | ||||
| 126 | # binmode( STDOUT, ":utf8" ); | |||||
| 127 | 0 | $template->process( $self->filename, $vars, \$data ) | ||||
| 128 | || die "Template process failed: ", $template->error(); | |||||
| 129 | 0 | return $data; | ||||
| 130 | } | |||||
| 131 | ||||||
| 132 | sub utf8_arrayref { | |||||
| 133 | 0 | my $arrayref = shift; | ||||
| 134 | 0 | foreach my $element (@$arrayref){ | ||||
| 135 | 0 | if (ref($element) eq 'ARRAY'){ | ||||
| 136 | 0 | utf8_arrayref($element); | ||||
| 137 | 0 | next; | ||||
| 138 | } | |||||
| 139 | 0 | if (ref($element) eq 'HASH'){ | ||||
| 140 | 0 | utf8_hashref($element); | ||||
| 141 | 0 | next; | ||||
| 142 | } | |||||
| 143 | 0 | utf8::encode($element) if utf8::is_utf8($element); | ||||
| 144 | } | |||||
| 145 | } | |||||
| 146 | ||||||
| 147 | sub utf8_hashref { | |||||
| 148 | 0 | my $hashref = shift; | ||||
| 149 | 0 0 | for my $key (keys %{$hashref}){ | ||||
| 150 | 0 | if (ref($hashref->{$key}) eq 'ARRAY'){ | ||||
| 151 | 0 | utf8_arrayref($hashref->{$key}); | ||||
| 152 | 0 | next; | ||||
| 153 | } | |||||
| 154 | 0 | if (ref($hashref->{$key}) eq 'HASH'){ | ||||
| 155 | 0 | utf8_hashref($hashref->{$key}); | ||||
| 156 | 0 | next; | ||||
| 157 | } | |||||
| 158 | 0 | utf8::encode($hashref->{$key}) if utf8::is_utf8($hashref->{$key}); | ||||
| 159 | } | |||||
| 160 | } | |||||
| 161 | ||||||
| 162 | ||||||
| 163 | # FIXME - this is a horrible hack to cache | |||||
| 164 | # the current known-good language, temporarily | |||||
| 165 | # put in place to resolve bug 4403. It is | |||||
| 166 | # used only by C4::XSLT::XSLTParse4Display; | |||||
| 167 | # the language is set via the usual call | |||||
| 168 | # to themelanguage. | |||||
| 169 | my $_current_language = 'en'; | |||||
| 170 | ||||||
| 171 | sub _current_language { | |||||
| 172 | 0 | return $_current_language; | ||||
| 173 | } | |||||
| 174 | ||||||
| 175 | ||||||
| 176 | # wrapper method to allow easier transition from HTML template pro to Template Toolkit | |||||
| 177 | sub param { | |||||
| 178 | 0 | my $self = shift; | ||||
| 179 | 0 | while (@_) { | ||||
| 180 | 0 | my $key = shift; | ||||
| 181 | 0 | my $val = shift; | ||||
| 182 | 0 0 | if ( ref($val) eq 'ARRAY' && !scalar @$val ) { $val = undef; } | ||||
| 183 | 0 | elsif ( ref($val) eq 'HASH' && !scalar %$val ) { $val = undef; } | ||||
| 184 | 0 | if ( $key ) { | ||||
| 185 | 0 | $self->{VARS}->{$key} = $val; | ||||
| 186 | } else { | |||||
| 187 | 0 | warn "Problem = a value of $val has been passed to param without key"; | ||||
| 188 | } | |||||
| 189 | } | |||||
| 190 | } | |||||
| 191 | ||||||
| 192 | ||||||
| 193 - 199 | =head1 NAME C4::Templates - Functions for managing templates =head1 FUNCTIONS =cut | |||||
| 200 | ||||||
| 201 | # FIXME: this is a quick fix to stop rc1 installing broken | |||||
| 202 | # Still trying to figure out the correct fix. | |||||
| 203 | my $path = C4::Context->config('intrahtdocs') . "/prog/en/includes/"; | |||||
| 204 | ||||||
| 205 | #--------------------------------------------------------------------------------------------------------- | |||||
| 206 | # FIXME - POD | |||||
| 207 | ||||||
| 208 | sub _get_template_file { | |||||
| 209 | 0 | my ($tmplbase, $interface, $query) = @_; | ||||
| 210 | ||||||
| 211 | 0 | my $is_intranet = $interface eq 'intranet'; | ||||
| 212 | 0 | my $htdocs = C4::Context->config($is_intranet ? 'intrahtdocs' : 'opachtdocs'); | ||||
| 213 | 0 | my ($theme, $lang) = themelanguage($htdocs, $tmplbase, $interface, $query); | ||||
| 214 | 0 | my $opacstylesheet = C4::Context->preference('opacstylesheet'); | ||||
| 215 | ||||||
| 216 | # if the template doesn't exist, load the English one as a last resort | |||||
| 217 | 0 | my $filename = "$htdocs/$theme/$lang/modules/$tmplbase"; | ||||
| 218 | 0 | unless (-f $filename) { | ||||
| 219 | 0 | $lang = 'en'; | ||||
| 220 | 0 | $filename = "$htdocs/$theme/$lang/modules/$tmplbase"; | ||||
| 221 | } | |||||
| 222 | 0 | return ($htdocs, $theme, $lang, $filename); | ||||
| 223 | } | |||||
| 224 | ||||||
| 225 | ||||||
| 226 | sub gettemplate { | |||||
| 227 | 0 | my ( $tmplbase, $interface, $query ) = @_; | ||||
| 228 | 0 | ($query) or warn "no query in gettemplate"; | ||||
| 229 | 0 | my $path = C4::Context->preference('intranet_includes') || 'includes'; | ||||
| 230 | 0 | my $opacstylesheet = C4::Context->preference('opacstylesheet'); | ||||
| 231 | 0 | $tmplbase =~ s/\.tmpl$/.tt/; | ||||
| 232 | 0 | my ($htdocs, $theme, $lang, $filename) | ||||
| 233 | = _get_template_file($tmplbase, $interface, $query); | |||||
| 234 | 0 | my $template = C4::Templates->new($interface, $filename, $tmplbase, $query); | ||||
| 235 | 0 | my $is_intranet = $interface eq 'intranet'; | ||||
| 236 | 0 | my $themelang = | ||||
| 237 | ($is_intranet ? '/intranet-tmpl' : '/opac-tmpl') . | |||||
| 238 | "/$theme/$lang"; | |||||
| 239 | 0 | $template->param( | ||||
| 240 | themelang => $themelang, | |||||
| 241 | yuipath => C4::Context->preference("yuipath") eq "local" | |||||
| 242 | ? "$themelang/lib/yui" | |||||
| 243 | : C4::Context->preference("yuipath"), | |||||
| 244 | interface => $is_intranet ? '/intranet-tmpl' : '/opac-tmpl', | |||||
| 245 | theme => $theme, | |||||
| 246 | lang => $lang | |||||
| 247 | ); | |||||
| 248 | ||||||
| 249 | # Bidirectionality | |||||
| 250 | 0 | my $current_lang = regex_lang_subtags($lang); | ||||
| 251 | 0 | my $bidi; | ||||
| 252 | 0 | $bidi = get_bidi($current_lang->{script}) if $current_lang->{script}; | ||||
| 253 | # Languages | |||||
| 254 | 0 | my $languages_loop = getTranslatedLanguages($interface,$theme,$lang); | ||||
| 255 | 0 | my $num_languages_enabled = 0; | ||||
| 256 | 0 | foreach my $lang (@$languages_loop) { | ||||
| 257 | 0 0 | foreach my $sublang (@{ $lang->{'sublanguages_loop'} }) { | ||||
| 258 | 0 | $num_languages_enabled++ if $sublang->{enabled}; | ||||
| 259 | } | |||||
| 260 | } | |||||
| 261 | $template->param( | |||||
| 262 | 0 | languages_loop => $languages_loop, | ||||
| 263 | bidi => $bidi, | |||||
| 264 | one_language_enabled => ($num_languages_enabled <= 1) ? 1 : 0, # deal with zero enabled langs as well | |||||
| 265 | ) unless @$languages_loop<2; | |||||
| 266 | ||||||
| 267 | 0 | return $template; | ||||
| 268 | } | |||||
| 269 | ||||||
| 270 | ||||||
| 271 | #--------------------------------------------------------------------------------------------------------- | |||||
| 272 | # FIXME - POD | |||||
| 273 | sub themelanguage { | |||||
| 274 | 0 | my ($htdocs, $tmpl, $interface, $query) = @_; | ||||
| 275 | 0 | ($query) or warn "no query in themelanguage"; | ||||
| 276 | ||||||
| 277 | # Select a language based on cookie, syspref available languages & browser | |||||
| 278 | 0 | my $lang = getlanguage($query, $interface); | ||||
| 279 | ||||||
| 280 | # Select theme | |||||
| 281 | 0 | my $is_intranet = $interface eq 'intranet'; | ||||
| 282 | 0 | my @themes = split(" ", C4::Context->preference( | ||||
| 283 | $is_intranet ? "template" : "opacthemes" )); | |||||
| 284 | 0 | push @themes, 'prog'; | ||||
| 285 | ||||||
| 286 | # Try to find first theme for the selected language | |||||
| 287 | 0 | for my $theme (@themes) { | ||||
| 288 | 0 | if ( -e "$htdocs/$theme/$lang/modules/$tmpl" ) { | ||||
| 289 | 0 | $_current_language = $lang; | ||||
| 290 | 0 | return ($theme, $lang) | ||||
| 291 | } | |||||
| 292 | } | |||||
| 293 | # Otherwise, return prog theme in English 'en' | |||||
| 294 | 0 | return ('prog', 'en'); | ||||
| 295 | } | |||||
| 296 | ||||||
| 297 | ||||||
| 298 | sub setlanguagecookie { | |||||
| 299 | 0 | my ( $query, $language, $uri ) = @_; | ||||
| 300 | 0 | my $cookie = $query->cookie( | ||||
| 301 | -name => 'KohaOpacLanguage', | |||||
| 302 | -value => $language, | |||||
| 303 | -expires => '' | |||||
| 304 | ); | |||||
| 305 | 0 | print $query->redirect( | ||||
| 306 | -uri => $uri, | |||||
| 307 | -cookie => $cookie | |||||
| 308 | ); | |||||
| 309 | } | |||||
| 310 | ||||||
| 311 | ||||||
| 312 | sub getlanguage { | |||||
| 313 | 0 | my ($query, $interface) = @_; | ||||
| 314 | ||||||
| 315 | # Select a language based on cookie, syspref available languages & browser | |||||
| 316 | 0 | my $is_intranet = $interface eq 'intranet'; | ||||
| 317 | 0 | my @languages = split(",", C4::Context->preference( | ||||
| 318 | $is_intranet ? 'language' : 'opaclanguages')); | |||||
| 319 | ||||||
| 320 | 0 | my $lang; | ||||
| 321 | ||||||
| 322 | # cookie | |||||
| 323 | 0 | if ( $query->cookie('KohaOpacLanguage') ) { | ||||
| 324 | 0 | $lang = $query->cookie('KohaOpacLanguage'); | ||||
| 325 | 0 | $lang =~ s/[^a-zA-Z_-]*//; # sanitize cookie | ||||
| 326 | } | |||||
| 327 | ||||||
| 328 | # HTTP_ACCEPT_LANGUAGE | |||||
| 329 | 0 | unless ($lang) { | ||||
| 330 | 0 | my $http_accept_language = $ENV{ HTTP_ACCEPT_LANGUAGE }; | ||||
| 331 | 0 | $lang = accept_language( $http_accept_language, | ||||
| 332 | getTranslatedLanguages($interface,'prog') ); | |||||
| 333 | } | |||||
| 334 | ||||||
| 335 | # Ignore a lang not selected in sysprefs | |||||
| 336 | 0 0 | $lang = undef unless first { $_ eq $lang } @languages; | ||||
| 337 | ||||||
| 338 | # Fall back to English if necessary | |||||
| 339 | 0 | $lang = 'en' unless $lang; | ||||
| 340 | ||||||
| 341 | 0 | return $lang; | ||||
| 342 | } | |||||
| 343 | ||||||
| 344 | 1; | |||||
| 345 | ||||||