]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/WWW/EGWeb.pm
Merging acq-experiment to trunk, since rel_1_4 has been branched.
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / WWW / EGWeb.pm
1 package OpenILS::WWW::EGWeb;
2 use strict; use warnings;
3 use Template;
4 use XML::Simple;
5 use File::stat;
6 use Apache2::Const -compile => qw(OK DECLINED HTTP_INTERNAL_SERVER_ERROR);
7 use Apache2::Log;
8
9 use constant OILS_HTTP_COOKIE_SKIN => 'oils:skin';
10 use constant OILS_HTTP_COOKIE_THEME => 'oils:theme';
11 use constant OILS_HTTP_COOKIE_LOCALE => 'oils:locale';
12
13 my $web_config;
14 my $web_config_file;
15 my $web_config_edit_time;
16
17 sub import {
18     my $self = shift;
19     $web_config_file = shift;
20     unless(-r $web_config_file) {
21         warn "Invalid web config $web_config_file";
22         return;
23     }
24     check_web_config();
25 }
26
27
28 sub handler {
29     my $r = shift;
30     check_web_config($r); # option to disable this
31     my $ctx = load_context($r);
32     my $base = $ctx->{base_uri};
33     my($template, $page_args) = find_template($r, $base);
34     return Apache2::Const::DECLINED unless $template;
35
36     $template = $ctx->{skin} . "/$template";
37     $ctx->{page_args} = $page_args;
38     $r->content_type('text/html; encoding=utf8');
39
40     my $tt = Template->new({
41         OUTPUT => $r,
42         INCLUDE_PATH => $ctx->{template_paths},
43     });
44
45     unless($tt->process($template, {ctx => $ctx})) {
46         $r->log->warn('Template error: ' . $tt->error);
47         return Apache2::Const::HTTP_INTERNAL_SERVER_ERROR;
48     }
49
50     return Apache2::Const::OK;
51 }
52
53 sub load_context {
54     my $r = shift;
55     my $cgi = CGI->new;
56     my $ctx = $web_config->{ctx};
57     $ctx->{skin} = $cgi->cookie(OILS_HTTP_COOKIE_SKIN) || 'default';
58     $ctx->{theme} = $cgi->cookie(OILS_HTTP_COOKIE_THEME) || 'default';
59     $ctx->{locale} = 
60         $r->headers_in->get('Accept-Language') || # this will need some trimming
61         $cgi->cookie(OILS_HTTP_COOKIE_LOCALE) || 'en-US';
62     $r->log->debug('skin = ' . $ctx->{skin} . ' : theme = ' . 
63         $ctx->{theme} . ' : locale = ' . $ctx->{locale});
64     return $ctx;
65 }
66
67 # Given a URI, finds the configured template and any extra page 
68 # arguments (trailing path info).  Any extra data is returned
69 # as page arguments, in the form of an array, one item per 
70 # /-separated URI component
71 sub find_template {
72     my $r = shift;
73     my $base = shift;
74     my $path = $r->uri;
75     $path =~ s/$base//og;
76     my @parts = split('/', $path);
77     my $template = '';
78     my $page_args = [];
79     my $handler = $web_config->{handlers};
80     while(@parts) {
81         my $part = shift @parts;
82         next unless $part;
83         my $t = $handler->{$part};
84         if(ref $t) {
85             $handler = $t;
86         } else {
87             $template = $t;
88             $page_args = [@parts];
89             last;
90         }
91     }
92
93     unless($template) {
94         $r->log->warn("No template configured for path $path");
95         return ();
96     }
97
98     $r->log->debug("template = $template : page args = @$page_args");
99     return ($template, $page_args);
100 }
101
102 # if the web configuration file has never been loaded or has
103 # changed since the last load, reload it
104 sub check_web_config {
105     my $r = shift;
106     my $epoch = stat($web_config_file)->mtime;
107     unless($web_config_edit_time and $web_config_edit_time == $epoch) {
108         $r->log->debug("Reloading web config after edit...") if $r;
109         $web_config_edit_time = $epoch;
110         $web_config = parse_config($web_config_file);
111     }
112 }
113
114 sub parse_config {
115     my $cfg_file = shift;
116     my $data = XML::Simple->new->XMLin($cfg_file);
117     my $ctx = {};
118     my $handlers = {};
119
120     $ctx->{media_prefix} = (ref $data->{media_prefix}) ? '' : $data->{media_prefix};
121     $ctx->{base_uri} = (ref $data->{base_uri}) ? '' : $data->{base_uri};
122     $ctx->{template_paths} = [];
123
124     my $tpaths = $data->{template_paths}->{path};
125     $tpaths = [$tpaths] unless ref $tpaths;
126     push(@{$ctx->{template_paths}}, $_) for @$tpaths;
127
128     for my $handler (@{$data->{handlers}->{handler}}) {
129         my @parts = split('/', $handler->{path});
130         my $h = $handlers;
131         my $pcount = scalar(@parts);
132         for(my $i = 0; $i < $pcount; $i++) {
133             my $p = $parts[$i];
134             unless(defined $h->{$p}) {
135                 if($i == $pcount - 1) {
136                     $h->{$p} = $handler->{template};
137                     last;
138                 } else {
139                     $h->{$p} = {};
140                 }
141             }
142             $h = $h->{$p};
143         }
144     }
145
146     return {ctx => $ctx, handlers => $handlers};
147 }
148
149
150 1;