1 package OpenILS::Application::Trigger::Reactor;
2 use strict; use warnings;
3 use Encode qw/ encode /;
6 use DateTime::Format::ISO8601;
7 use Unicode::Normalize;
9 use OpenSRF::Utils qw/:datetime/;
10 use OpenSRF::Utils::Logger qw(:logger);
11 use OpenILS::Application::AppUtils;
12 use OpenILS::Utils::CStoreEditor qw/:funcs/;
13 my $U = 'OpenILS::Application::AppUtils';
15 sub fourty_two { return 42 }
16 sub NOOP_True { return 1 }
17 sub NOOP_False { return 0 }
20 # To be used in two places within $_TT_helpers. Without putting the code out
21 # here, we can't really reuse it within that structure.
23 my $name = shift or return; # the first arg is always the name
24 my ($type, $attr) = (scalar(@_) == 1) ? (undef, $_[0]) : @_;
25 # if the next is the last, it's the attributes, otherwise type
26 # use Data::Dumper; $logger->warn("get_li_attr: " . Dumper($attr));
27 ($name and @$attr) or return;
29 $name =~ s/^(\D+)_(\d+)$/$1/ and $length = $2;
31 $_->attr_name eq $name or next;
32 next if $length and $length != length($_->attr_value);
33 return $_->attr_value if (! $type) or $type eq $_->attr_type;
38 # helper functions inserted into the TT environment
41 # turns a date into something TT can understand
44 $date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($date));
46 "%0.2d:%0.2d:%0.2d %0.2d-%0.2d-%0.4d",
56 # escapes a string for inclusion in an XML document. escapes &, <, and > characters
59 $str =~ s/&/&/sog;
67 $str =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
71 # encode email headers in UTF-8, per RFC2231
72 escape_email_header => sub {
74 $str = encode("MIME-Header", $str);
78 # strip non-ASCII characters after splitting base characters and diacritics
79 # least common denominator for EDIFACT messages using the UNOB character set
80 force_jedi_unob => sub {
83 $str =~ s/[\x{0080}-\x{fffd}]//g;
87 # returns the calculated user locale
88 get_user_locale => sub {
90 return $U->get_user_locale($user_id);
93 # returns the calculated copy price
94 get_copy_price => sub {
96 return $U->get_copy_price(new_editor(xact=>1), $copy_id);
99 # given a copy, returns the title and author in a hash
100 get_copy_bib_basics => sub {
102 my $copy = new_editor(xact=>1)->retrieve_asset_copy([
107 acp => ['call_number'],
112 if($copy->call_number->id == -1) {
114 title => $copy->dummy_title,
115 author => $copy->dummy_author,
118 my $mvr = $U->record_to_mvr($copy->call_number->record);
120 title => $mvr->title,
121 author => $mvr->author
126 # returns the org unit setting value
127 get_org_setting => sub {
128 my($org_id, $setting) = @_;
129 return $U->ou_ancestor_setting_value($org_id, $setting);
132 # This basically greps/maps out ths isbn string values, but also promotes the first isbn-13 to the
133 # front of the line (so that the EDI translator takes it as primary) if there is one.
134 get_li_isbns => sub {
139 $_->attr_name eq 'isbn' or next;
140 my $val = $_->attr_value;
141 if (! $primary and length($val) == 13) {
147 $primary and unshift @isbns, $primary;
148 $logger->debug("get_li_isbns returning isbns: " . join(', ', @isbns));
152 # helpers.get_li_attr('isbn_13', li.attributes)
153 # returns matching line item attribute, or undef
154 get_li_attr => \&get_li_attr,
156 get_li_attr_jedi => sub {
157 my $value = get_li_attr(@_);
159 # Here we can add any number of special case transformations to
160 # avoid problems with the EDI translator (or bad JSON).
162 # The ? character, if in the final position of a string, breaks
163 # the translator. + or ' or : could be problematic, too.
164 if ($value =~ /[\?\+':]$/) {
168 # Make sure any double quotation marks are escaped.
171 # What the heck, get rid of [ ] too (although I couldn't get them
172 # to cause any problems for me.
173 $value =~ s/[\[\]]//g;
179 get_queued_bib_attr => sub {
180 my $name = shift or return; # the first arg is always the name
182 # use Data::Dumper; $logger->warn("get_queued_bib_attr: " . Dumper($attr));
183 ($name and @$attr) or return;
186 select => {'vqbrad' => ['id']},
188 where => {code => $name}
191 my $def_ids = new_editor()->json_query($query);
195 $name =~ s/^(\D+)_(\d+)$/$1/ and $length = $2;
197 $_->field eq @{$def_ids}[0]->{id} or next;
198 next if $length and $length != length($_->attr_value);
199 return $_->attr_value;
204 get_queued_auth_attr => sub {
205 my $name = shift or return; # the first arg is always the name
207 # use Data::Dumper; $logger->warn("get_queued_auth_attr: " . Dumper($attr));
208 ($name and @$attr) or return;
211 select => {'vqarad' => ['id']},
213 where => {code => $name}
216 my $def_ids = new_editor()->json_query($query);
220 $name =~ s/^(\D+)_(\d+)$/$1/ and $length = $2;
222 $_->field eq @{$def_ids}[0]->{id} or next;
223 next if $length and $length != length($_->attr_value);
224 return $_->attr_value;
232 if ($str =~ /\,/ || $str =~ /"/) {
234 $str = '"' . $str . '"';
241 bre_open_hold_count => sub {
243 return 0 unless $bre_id;
244 return $U->simplereq(
246 'open-ils.circ.bre.holds.count', $bre_id);
251 return $str ? (new XML::LibXML)->parse_string($str) : undef;
257 # processes templates. Returns template output on success, undef on error
262 return undef unless $env->{template};
266 my $tt = Template->new;
267 # my $tt = Template->new(ENCODING => 'utf8'); # ??
268 $env->{helpers} = $_TT_helpers;
270 unless( $tt->process(\$env->{template}, $env, \$output) ) {
272 ($error = $tt->error) =~ s/\n/ /og;
273 $logger->error("Error processing Trigger template: $error");
276 if ( $error or (!$nostore && $output) ) {
277 my $t_o = Fieldmapper::action_trigger::event_output->new;
278 $t_o->data( ($error) ? $error : $output );
279 $t_o->is_error( ($error) ? 't' : 'f' );
280 $logger->info("trigger: writing " . length($t_o->data) . " bytes to template output");
282 $env->{EventProcessor}->editor->xact_begin;
283 $t_o = $env->{EventProcessor}->editor->create_action_trigger_event_output( $t_o );
285 my $state = (ref $$env{event} eq 'ARRAY') ? $$env{event}->[0]->state : $env->{event}->state;
286 my $key = ($error) ? 'error_output' : 'template_output';
287 $env->{EventProcessor}->update_state( $state, { $key => $t_o->id } );