File Coverage

blib/lib/Workflow/Exception.pm
Criterion Covered Total %
statement 40 40 100.0
branch 2 2 100.0
condition n/a
subroutine 12 12 100.0
pod 5 5 100.0
total 59 59 100.0


line stmt bran cond sub pod time code
1             package Workflow::Exception;
2              
3 58     58   551461 use warnings;
  58         155  
  58         4660  
4 58     58   379 use strict;
  58         109  
  58         1443  
5 58     58   805 use v5.14.0;
  58         348  
6              
7             # Declare some of our exceptions...
8              
9             use Exception::Class (
10 58         990 'Workflow::Exception::Configuration' => {
11             isa => 'Workflow::Exception',
12             description => 'Configuration errors',
13             },
14             'Workflow::Exception::Persist' => {
15             isa => 'Workflow::Exception',
16             description => 'Persistence errors',
17             },
18             'Workflow::Exception::Validation' => {
19             isa => 'Workflow::Exception',
20             description => 'Validation errors',
21             fields => 'invalid_fields',
22             },
23 58     58   19475 );
  58         302974  
24              
25 58     58   70013 use Log::Any;
  58         57858  
  58         490  
26              
27             my %TYPE_CLASSES = (
28             configuration_error => 'Workflow::Exception::Configuration',
29             persist_error => 'Workflow::Exception::Persist',
30             validation_error => 'Workflow::Exception::Validation',
31             workflow_error => 'Workflow::Exception',
32             );
33             my %TYPE_LOGGING = (
34             configuration_error => 'error',
35             persist_error => 'error',
36             validation_error => 'info',
37             workflow_error => 'error',
38             );
39              
40              
41             $Workflow::Exception::VERSION = '2.09';
42             @Workflow::Exception::ISA = qw( Exporter Exception::Class::Base );
43             @Workflow::Exception::EXPORT_OK = keys %TYPE_CLASSES;
44              
45             # Exported shortcuts
46              
47             sub _mythrow {
48 28     28   100 my ( $type, @items ) = @_;
49              
50 28         93 my ( $msg, %params ) = _massage(@items);
51 28         103 my $caller = caller;
52 28         1242 my $log = Log::Any->get_logger( category => $caller ); # log as if part of the package of the caller
53 28         13259 my ( $pkg, $line ) = (caller)[ 0, 2 ];
54 28         1036 my ( $prev_pkg, $prev_line ) = ( caller 1 )[ 0, 2 ];
55              
56             # Do not log condition errors
57 28         1030 my $method = $TYPE_LOGGING{$type};
58 28         236 $log->$method(
59             "$type exception thrown from [$pkg: $line; before: ",
60             "$prev_pkg: $prev_line]: $msg"
61             );
62              
63             goto &Exception::Class::Base::throw(
64 28         207 $TYPE_CLASSES{$type},
65             message => $msg,
66             %params
67             );
68             }
69              
70             # Use 'goto' here to maintain the stack trace
71              
72             sub configuration_error {
73 11     11 1 4319 unshift @_, 'configuration_error';
74 11         55 goto &_mythrow;
75             }
76              
77             sub persist_error {
78 6     6 1 2599 unshift @_, 'persist_error';
79 6         24 goto &_mythrow;
80             }
81              
82             sub validation_error {
83 4     4 1 1431 unshift @_, 'validation_error';
84 4         13 goto &_mythrow;
85             }
86              
87             sub workflow_error {
88 7     7 1 875 unshift @_, 'workflow_error';
89 7         57 goto &_mythrow;
90             }
91              
92             # Override 'throw' so we can massage the message and parameters into
93             # the right format for E::C
94              
95             sub throw {
96 1     1 1 3701 my ( $class, @items ) = @_;
97              
98 1         5 my ( $msg, %params ) = _massage(@items);
99 1         5 goto &Exception::Class::Base::throw( $class, message => $msg, %params );
100             }
101              
102             sub _massage {
103 29     29   72 my @items = @_;
104              
105 29 100       115 my %params = ( ref $items[-1] eq 'HASH' ) ? %{ pop @items } : ();
  1         5  
106 29         97 my $msg = join '', @items;
107 29         85 $msg =~ s/\\n/ /g; # don't log newlines as per Log4perl recommendations
108 29         124 return ( $msg, %params );
109             }
110              
111             1;
112              
113             __END__
114              
115             =pod
116              
117             =head1 NAME
118              
119             Workflow::Exception - Base class for workflow exceptions
120              
121             =head1 VERSION
122              
123             This documentation describes version 2.09 of this package
124              
125             =head1 SYNOPSIS
126              
127             # Standard usage
128             use Workflow::Exception qw( workflow_error );
129              
130             my $user = $wf->context->param( 'current_user' );
131             unless ( $user->check_password( $entered_password ) ) {
132             workflow_error "User exists but password check failed";
133             }
134              
135             # Pass a list of strings to form the message
136              
137             unless ( $user->check_password( $entered_password ) ) {
138             workflow_error 'Bad login: ', $object->login_attempted;
139             }
140              
141             # Using other exported shortcuts
142              
143             use Workflow::Exception qw( configuration_error );
144             configuration_error "Field 'foo' must be a set to 'bar'";
145              
146             use Workflow::Exception qw( validation_error );
147             validation_error "Validation for field 'foo' failed: $error";
148              
149             =head1 DESCRIPTION
150              
151             First, you should probably look at
152             L<Exception::Class|Exception::Class> for more usage examples, why we
153             use exceptions, what they are intended for, etc.
154              
155             This is the base class for all workflow exceptions. It declares a
156             handful of exceptions and provides shortcuts to make raising an
157             exception easier and more readable.
158              
159             =head1 METHODS
160              
161             =head3 throw( @msg, [ \%params ])
162              
163             This overrides B<throw()> from L<Exception::Class|Exception::Class> to
164             add a little syntactic sugar. Instead of:
165              
166             $exception_class->throw( message => 'This is my very long error message that I would like to pass',
167             param1 => 'Param1 value',
168             param2 => 'Param2 value' );
169              
170             You can use:
171              
172             $exception_class->throw( 'This is my very long error message ',
173             'that I would like to pass',
174             { param1 => 'Param1 value',
175             param2 => 'Param2 value' } );
176              
177             And everything will work the same. Combined with the L<SHORTCUTS> this
178             makes for very readable code:
179              
180             workflow_error "Something went horribly, terribly, dreadfully, "
181             "frightfully wrong: $@",
182             { foo => 'bar' };
183              
184             =head3 configuration_error
185              
186             This method transforms the error to a configuration error.
187              
188             This exception is thrown via </mythrow> when configuration of a workflow is unsuccessful.
189              
190             =head3 persist_error
191              
192             This method transforms the error to a persistance error.
193              
194             This exception is thrown via </mythrow> when the save of a workflow is unsuccessful.
195              
196             =head3 validation_error
197              
198             This method transforms the error to a validation error.
199              
200             This exception is thrown via </mythrow> when input data or similar of a workflow is unsuccessful.
201              
202             =head3 workflow_error
203              
204             This method transforms the error to a workflow error.
205              
206             This exception is thrown via </mythrow> when input data or similar of a workflow is unsuccessful.
207              
208             =head1 SHORTCUTS
209              
210             =over
211              
212             =item * B<Workflow::Exception> - import using C<workflow_error>
213              
214             =item * B<Workflow::Exception::Configuration> - import using C<configuration_error>
215              
216             =item * B<Workflow::Exception::Persist> - import using C<persist_error>
217              
218             =item * B<Workflow::Exception::Validation> - import using C<validation_error>
219              
220             =back
221              
222             =head1 SEE ALSO
223              
224             =over
225              
226             =item * L<Exception::Class|Exception::Class>
227              
228             =back
229              
230             =head1 COPYRIGHT
231              
232             Copyright (c) 2003-2021 Chris Winters. All rights reserved.
233              
234             This library is free software; you can redistribute it and/or modify
235             it under the same terms as Perl itself.
236              
237             Please see the F<LICENSE>
238              
239             =head1 AUTHORS
240              
241             Please see L<Workflow>
242              
243             =cut