package Transform::Alert::TemplateGrp; our $VERSION = '1.00'; # VERSION # ABSTRACT: Base class for Transform::Alert template groups use sanity; use Moo; use MooX::Types::MooseLike::Base qw(Bool Str ArrayRef RegexpRef HashRef InstanceOf ConsumerOf Maybe); use Template 2.24; use Data::Dump 'pp'; use File::Slurp 'read_file'; use String::Escape qw(elide printable); use Module::Load; # yes, using both Class::Load and Module::Load, as M:L will load files use Module::Metadata; use namespace::clean; has in_group => ( is => 'rwp', isa => InstanceOf['Transform::Alert::InputGrp'], weak_ref => 1, handles => [ 'log' ], ); has regexp => ( is => 'ro', isa => Maybe[RegexpRef], required => 1, ); has munger => ( is => 'ro', isa => ArrayRef[Str], predicate => 1, ); has outputs => ( is => 'ro', isa => HashRef[ConsumerOf['Transform::Alert::Output']], required => 1, ); around BUILDARGS => sub { my ($orig, $self) = (shift, shift); my $hash = shift; $hash = { $hash, @_ } unless ref $hash; # temp hash with output objects my $outs = delete $hash->{output_objs}; # replace OutputNames with Outputs my $outputs = delete $hash->{outputname}; $outputs = [ $outputs ] unless (ref $outputs eq 'ARRAY'); $hash->{outputs} = { map { $_ => ($outs->{$_} || die "OutputName '$_' doesn't have a matching Output block!") } @$outputs }; # read template file if ($hash->{templatefile}) { $hash->{regexp} = read_file( delete $hash->{templatefile} ); } elsif ($hash->{template}) { $hash->{regexp} = delete $hash->{template}; } else { $hash->{regexp} = undef; } # work with inline templates (and file above) if ($hash->{regexp} && not ref $hash->{regexp}) { my $tmpl_text = $hash->{regexp}; $tmpl_text =~ s/^\s+|\s+$//g; # remove leading/trailing spaces $tmpl_text =~ s/\r//g; # make sure it works for all line-endings $tmpl_text = '^'.$tmpl_text.'$'; $hash->{regexp} = qr/$tmpl_text/; } # munger class if (my $munger = delete $hash->{munger}) { # variable parsing my ($file, $class, $fc, $method); ($fc, $method) = split /-\>/, $munger, 2; ($file, $class) = split /\s+/, $fc, 2; unless ($class) { my $info = Module::Metadata->new_from_file($file); $class = ($info->packages_inside)[0]; die "No packages found in $file!" unless $class; } $method ||= 'munge'; load $file; $hash->{munger} = [ $class, $method ]; } $orig->($self, $hash); }; sub send_all { my ($self, $vars) = @_; my $log = $self->log; $log->debug('Processing outputs...'); $log->trace('Variables (pre-munged):'); $log->trace( join "\n", map { ' '.$_ } split(/\n/, pp $vars) ); # Munge the data if configured if ($self->munger) { my ($class, $method) = @{ $self->munger }; no strict 'refs'; $vars = $class->$method($vars, $self); unless ($vars) { $log->debug('Munger cancelled output'); return 1; } $log->trace('Variables (post-munge):'); $log->trace( join "\n", map { ' '.$_ } split(/\n/, pp $vars) ); } # Support multiple outputs, if the munger sent them $vars = [ $vars ] unless (ref $vars eq 'ARRAY'); my $tt = Template->new(); foreach my $v (@$vars) { foreach my $out_key (keys %{ $self->outputs }) { $log->debug('Looking at Output "'.$out_key.'"...'); my $out = $self->outputs->{$out_key}; my $out_str = ''; $tt->process($out->template, $v, \$out_str) || do { $log->error('TT error for "$out_key": '.$tt->error); $log->warn('Output error... bailing out of this process cycle!'); $self->close_all; return; }; # send alert unless ($out->opened) { $log->debug('Opening output connection'); $out->open; } $log->info('Sending alert for "'.$out_key.'"'); $log->info(' Output message: '.printable(elide($out_str, int(2.5 ** $log->level) )) ); unless ($out->send(\$out_str)) { $log->warn('Output error... bailing out of this process cycle!'); $self->close_all; return; } } } return 1; } sub close_all { my $self = shift; $_->close for (values %{ $self->outputs }); return 1; } 42; __END__ =pod =encoding utf-8 =head1 NAME Transform::Alert::TemplateGrp - Base class for Transform::Alert template groups =head1 SYNOPSIS # In your configuration =head1 DESCRIPTION This is essentially a class used for handling C<<< Template >>> sections. In the grand scheme of things, the classes follow this hierarchy: transalert_ctl Transform::Alert TA::InputGrp TA::Input::* TA::TemplateGrp TA::Output::* (referenced from the main TA object) TA::Output::* (stored list only) In fact, the configuration file is parsed recursively in this fashion. However, this isn't really a user-friendly interface. So, shoo! =head1 SEE ALSO L, which is what you should really be reading... =head1 AVAILABILITY The project homepage is L. The latest version of this module is available from the Comprehensive Perl Archive Network (CPAN). Visit L to find a CPAN site near you, or see L. =head1 AUTHOR Brendan Byrd =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by Brendan Byrd. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut