From: Bill Erickson Date: Fri, 26 Apr 2013 17:20:24 +0000 (-0400) Subject: LP1171875 Add locale support to IDL2js X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=2bddeede1d84fd96df0bad2054bbce4cbefaca33;p=evergreen%2Fmasslnc.git LP1171875 Add locale support to IDL2js /IDL2js now reads locale information from either locale= CGI parameter or Accept-Language HTTP headers. The locale-aware IDL is loaded from /reports/fm_IDL.xml via Apache subrequest. Each full copy of the IDL is cached within the Apache processes to avoid the need to re-parse the IDL ad infinitum for full IDL retrieval. Partial IDL retrieval is also supported (but not cached). No attempt is made to cleanse the locale -- invalid locale strings are discarded -- so it's the callers responsibility to pass a valid locale. Signed-off-by: Bill Erickson Signed-off-by: Pasi Kallinen Signed-off-by: Mike Rylander --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/IDL2js.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/IDL2js.pm index c55f137be9..497b0dbc16 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/IDL2js.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/IDL2js.pm @@ -3,14 +3,18 @@ use strict; use warnings; use XML::LibXML; use XML::LibXSLT; use Apache2::Const -compile => qw(OK DECLINED HTTP_INTERNAL_SERVER_ERROR); +use Apache2::RequestRec; +use Apache2::SubRequest; +use Apache2::Filter; +use APR::Brigade; +use APR::Bucket; use Error qw/:try/; use OpenSRF::System; use OpenSRF::Utils::SettingsClient; +use CGI; my $bs_config; my $stylesheet; -my $idl_doc; - # load and parse the stylesheet sub import { @@ -48,21 +52,82 @@ sub child_init { warn "Invalid XSL File: $xsl_file: $e\n"; }; - $idl_doc = XML::LibXML->load_xml(location => $idl_file); return Apache2::Const::OK; } +my %idl_cache; sub handler { my $r = shift; my $args = $r->args || ''; child_init() unless $__initted; - return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR unless $stylesheet and $idl_doc; - return Apache2::Const::DECLINED if $args and $args !~ /^[a-zA-Z,]*$/; + return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR unless $stylesheet; + + # pull the locale from the query string if present + (my $locale = $args) =~ s/.*locale=([a-z]{2}-[A-Z]{2}).*/$1/g; + + # remove the locale argument from the query + # string, regardless of whether it was valid + $args =~ s/([&;]?locale=[^&;]*)[&;]?//g; + + # if no valid locale is present in the query + # string, pull it from the headers + $locale = $r->headers_in->get('Accept-Language') unless $locale; + + if (!$locale or $locale !~ /^[a-z]{2}-[A-Z]{2}$/) { + $r->log->debug("Invalid IDL2js locale '$locale'; using en-US"); + $locale = 'en-US'; + } + + $r->log->debug("IDL2js using locale '$locale'"); + + my $output = ''; + my $stat = load_IDL($r, $locale, $args, \$output); + return $stat unless $stat == Apache2::Const::OK; + + $r->content_type('application/x-javascript; encoding=utf8'); + $r->print($output); + return Apache2::Const::OK; +} + +# loads the IDL for the provided locale. +# when possible, use a cached version of the IDL. +sub load_IDL { + my ($r, $locale, $args, $output_ref) = @_; + + # do we already have a cached copy of the IDL for this locale? + if (!$args and $idl_cache{$locale}) { + $$output_ref = $idl_cache{$locale}; + return Apache2::Const::OK; + } + + # Fetch the locale-aware fm_IDL.xml via Apache subrequest. + my $subr = $r->lookup_uri("/reports/fm_IDL.xml?locale=$locale"); + + # filter allows us to capture the output of the subrequest locally + # http://www.gossamer-threads.com/lists/modperl/modperl/97649#97649 + my $xml = ''; + $subr->add_output_filter(sub { + my ($f, $bb) = @_; + while (my $e = $bb->first) { + $e->read(my $buf); + $xml .= $buf; + $e->delete; + } + return Apache2::Const::OK; + }); + + $subr->run; + + if (!$xml) { + $r->log->error("No IDL XML found"); + return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR; + } my $output; try { + my $idl_doc = XML::LibXML->load_xml(string => $xml); my $results = $stylesheet->transform($idl_doc, class_list => "'$args'"); $output = $stylesheet->output_as_bytes($results); } catch Error with { @@ -72,9 +137,13 @@ sub handler { return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR unless $output; - $r->content_type('application/x-javascript; encoding=utf8'); - $r->print($output); - return Apache2::Const::OK; + # only cache full versions of the IDL + $idl_cache{$locale} = $output unless $args; + + # pass output back to the caller + $$output_ref = $output; + + return Apache2::Const::OK; } 1;