1 package OpenILS::WWW::EGCatLoader;
2 use strict; use warnings;
3 use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
4 use OpenSRF::Utils::Logger qw/$logger/;
5 use OpenILS::Utils::CStoreEditor qw/:funcs/;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Application::AppUtils;
8 my $U = 'OpenILS::Application::AppUtils';
10 my $ro_object_subs; # cached subs
11 our %cache = ( # cached data
12 map => {aou => {}}, # others added dynamically as needed
17 sub init_ro_object_cache {
19 my $e = $self->editor;
23 # subs have been built. insert into the context then move along.
24 $ctx->{$_} = $ro_object_subs->{$_} for keys %$ro_object_subs;
28 # make all "field_safe" classes accesible by default in the template context
30 ($Fieldmapper::fieldmap->{$_}->{field_safe} || '') =~ /true/i
31 } keys %{ $Fieldmapper::fieldmap };
33 for my $class (@classes) {
35 my $hint = $Fieldmapper::fieldmap->{$class}->{hint};
36 next if $hint eq 'aou'; # handled separately
38 my $ident_field = $Fieldmapper::fieldmap->{$class}->{identity};
39 (my $eclass = $class) =~ s/Fieldmapper:://o;
42 my $list_key = "${hint}_list";
43 my $find_key = "find_$hint";
45 $ro_object_subs->{$list_key} = sub {
46 my $method = "retrieve_all_$eclass";
47 $cache{list}{$hint} = $e->$method() unless $cache{list}{$hint};
48 return $cache{list}{$hint};
51 $cache{map}{$hint} = {} unless $cache{map}{$hint};
53 $ro_object_subs->{$find_key} = sub {
55 return $cache{map}{$hint}{$id} if $cache{map}{$hint}{$id};
56 ($cache{map}{$hint}{$id}) = grep { $_->$ident_field eq $id } @{$ro_object_subs->{$list_key}->()};
57 return $cache{map}{$hint}{$id};
61 $ro_object_subs->{aou_tree} = sub {
63 # fetch the org unit tree
64 unless($cache{aou_tree}) {
65 my $tree = $e->search_actor_org_unit([
66 { parent_ou => undef},
68 flesh_fields => {aou => ['children']},
69 order_by => {aou => 'name'}
73 # flesh the org unit type for each org unit
74 # and simultaneously set the id => aou map cache
77 my $ro_object_subs = shift;
78 $node->ou_type( $ro_object_subs->{find_aout}->($node->ou_type) );
79 $cache{map}{aou}{$node->id} = $node;
80 flesh_aout($_, $ro_object_subs) foreach @{$node->children};
82 flesh_aout($tree, $ro_object_subs);
84 $cache{aou_tree} = $tree;
87 return $cache{aou_tree};
90 # Add a special handler for the tree-shaped org unit cache
91 $ro_object_subs->{find_aou} = sub {
93 $ro_object_subs->{aou_tree}->(); # force the org tree to load
94 return $cache{map}{aou}{$org_id};
97 # turns an ISO date into something TT can understand
98 $ro_object_subs->{parse_datetime} = sub {
100 $date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($date));
102 "%0.2d:%0.2d:%0.2d %0.2d-%0.2d-%0.4d",
112 # retrieve and cache org unit setting values
113 $ro_object_subs->{get_org_setting} = sub {
114 my($org_id, $setting) = @_;
116 $cache{org_settings}{$org_id} = {}
117 unless $cache{org_settings}{$org_id};
119 $cache{org_settings}{$org_id}{$setting} =
120 $U->ou_ancestor_setting_value($org_id, $setting)
121 unless exists $cache{org_settings}{$org_id}{$setting};
123 return $cache{org_settings}{$org_id}{$setting};
126 $ctx->{$_} = $ro_object_subs->{$_} for keys %$ro_object_subs;
129 sub generic_redirect {
132 my $cookie = shift; # can be an array of cgi.cookie's
134 $self->apache->print(
135 $self->cgi->redirect(
137 $self->cgi->param('redirect_to') ||
138 $self->ctx->{referer} ||
139 $self->ctx->{home_page},
144 return Apache2::Const::REDIRECT;
147 sub get_records_and_facets {
148 my ($self, $rec_ids, $facet_key) = @_;
150 my $cstore = OpenSRF::AppSession->create('open-ils.cstore');
151 my $bre_req = $cstore->request(
152 'open-ils.cstore.direct.biblio.record_entry.search', {id => $rec_ids}
155 my $search = OpenSRF::AppSession->create('open-ils.search');
156 my $facet_req = $search->request(
157 'open-ils.search.facet_cache.retrieve', $facet_key, 10
161 while (my $resp = $bre_req->recv) {
162 my $bre = $resp->content;
164 # XXX farm out to multiple cstore sessions before loop,
166 my $copy_counts = $self->editor->json_query(
167 {from => ['asset.record_copy_count', 1, $bre->id, 0]}
172 marc_xml => XML::LibXML->new->parse_string($bre->marc),
173 copy_counts => $copy_counts
181 $facets = $facet_req->gather(1);
184 cmf => $self->ctx->{find_cmf}->($_),
185 data => $facets->{$_}
186 } for keys %$facets; # quick-n-dirty
191 return ($facets, @data);
194 sub fetch_marc_xml_by_id {
195 my ($self, $id_list) = @_;
196 $id_list = [$id_list] unless ref($id_list);
199 no warnings qw/numeric/;
200 $id_list = [map { int $_ } @$id_list];
201 $id_list = [grep { $_ > 0} @$id_list];
204 return {} if scalar(@$id_list) < 1;
206 # I'm just sure there needs to be some more efficient way to get all of
208 my $results = $self->editor->json_query({
209 "select" => {"bre" => ["id", "marc"]},
210 "from" => {"bre" => {}},
211 "where" => {"id" => $id_list}
212 }) or return $self->editor->die_event;
215 for my $r (@$results) {
216 $marc_xml->{$r->{"id"}} =
217 (new XML::LibXML)->parse_string($r->{"marc"});