package Workflow::Condition::Evaluate; # $Id: Evaluate.pm 285 2007-06-18 19:57:58Z jonasbn $ use strict; use base qw( Workflow::Condition ); use Log::Log4perl qw( get_logger ); use Safe; use Workflow::Exception qw( condition_error configuration_error ); $Workflow::Condition::Evaluate::VERSION = '1.02'; my @FIELDS = qw( test ); __PACKAGE__->mk_accessors( @FIELDS ); # These get put into the safe compartment... $Workflow::Condition::Evaluate::context = undef; my ( $log ); sub _init { my ( $self, $params ) = @_; $log ||= get_logger(); $self->test( $params->{test} ); unless ( $self->test ) { configuration_error "The evaluate condition must be configured with 'test'"; } $log->is_info && $log->info( "Added evaluation condition with '$params->{test}'" ); } sub evaluate { my ( $self, $wf ) = @_; $log ||= get_logger(); my $to_eval = $self->test; $log->is_info && $log->info( "Evaluating '$to_eval' to see if it returns true..." ); # Assign our local stuff to package variables... $Workflow::Condition::Evaluate::context = $wf->context->param; # Create the Safe compartment and safely eval the test... my $safe = Safe->new(); $safe->share( '$context' ); my $rv = $safe->reval( $to_eval ); if ( $@ ) { $log->error( "Eval code '$to_eval' threw exception: $@" ); condition_error "Condition expressed in code threw exception: $@"; } $log->is_debug && $log->debug( "Safe eval ran ok, returned: '$rv'" ); unless ( $rv ) { condition_error "Condition expressed by test '$to_eval' did not ", "return a true value."; } return $rv; } 1; __END__ =head1 NAME Workflow::Condition::Evaluate - Inline condition that evaluates perl code for truth =head1 SYNOPSIS =head1 DESCRIPTION If you've got a simple test you can use Perl code inline instead of specifying a condition class. We differentiate by the 'test' attribute -- if it's present we assume it's Perl code to be evaluated. While it's easy to abuse something like this with: {foo} =~ /^Pita (chips|snacks|bread)$/" ) { return $context->{bar} eq 'hummus'; } else { ... } ]]> It should provide a good balance. =head1 OBJECT METHODS =head3 new( \%params ) One of the C<\%params> should be 'test', which contains the text to evaluate for truth. =head3 evaluate( $wf ) Evaluate the text passed into the constructor: if the evaluation returns a true value then the condition passes; if it throws an exception or returns a false value, the condition fails. We use L to provide a restricted compartment in which we evaluate the text. This should prevent any sneaky bastards from doing something like: The text has access to one variable, for the moment: =over 4 =item B<$context> A hashref of all the parameters in the L object =back =head1 SEE ALSO L - From some quick research this module seems to have been packaged with core Perl 5.004+, and that's sufficiently ancient for me to not worry about people having it. If this is a problem for you shoot me an email. =head1 COPYRIGHT Copyright (c) 2004 Chris Winters. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHORS Chris Winters Echris@cwinters.comE