File Coverage

lib/Workflow/Persister/DBI/ExtraData.pm
Criterion Covered Total %
statement 18 62 29.0
branch 0 14 0.0
condition 0 3 0.0
subroutine 6 10 60.0
pod 2 2 100.0
total 26 91 28.5


line stmt bran cond sub pod time code
1              
2             use warnings;
3 1     1   17214 use strict;
  1         2  
  1         31  
4 1     1   4 use base qw( Workflow::Persister::DBI );
  1         2  
  1         19  
5 1     1   4 use Log::Log4perl qw( get_logger );
  1         1  
  1         387  
6 1     1   6 use Workflow::Exception qw( configuration_error persist_error );
  1         1  
  1         6  
7 1     1   49 use English qw( -no_match_vars );
  1         2  
  1         38  
8 1     1   4  
  1         2  
  1         4  
9             $Workflow::Persister::DBI::ExtraData::VERSION = '1.60';
10              
11             my @FIELDS = qw( table data_field context_key );
12             __PACKAGE__->mk_accessors(@FIELDS);
13              
14             my ( $self, $params ) = @_;
15             $self->SUPER::init($params);
16 0     0 1    
17 0           my @not_found = ();
18             foreach (qw( table data_field )) {
19 0           push @not_found, $_ unless ( $params->{"extra_$_"} );
20 0           }
21 0 0         if ( scalar @not_found ) {
22             $self->log->error( "Required configuration fields not found: ",
23 0 0         join ', ', @not_found );
24 0           configuration_error
25             "To fetch extra data with each workflow with this implementation ",
26 0           "you must specify: ", join ', ', @not_found;
27             }
28              
29             $self->table( $params->{extra_table} );
30             my $data_field = $params->{extra_data_field};
31 0            
32 0           # If multiple data fields specified we don't allow the user to
33             # specify a context key
34              
35             if ( $data_field =~ /,/ ) {
36             $self->data_field( [ split /\s*,\s*/, $data_field ] );
37 0 0         } else {
38 0           $self->data_field($data_field);
39             my $context_key = $params->{extra_context_key} || $data_field;
40 0           $self->context_key($context_key);
41 0   0       }
42 0           $self->log->info( "Configured extra data fetch with: ",
43             join( '; ', $self->table, $data_field,
44 0 0         ( defined $self->context_key
45             ? $self->context_key : '' ) ) );
46             }
47              
48             my ( $self, $wf ) = @_;
49              
50             $self->log->debug( "Fetching extra workflow data for '", $wf->id, "'" );
51 0     0 1    
52             my $sql = q{SELECT %s FROM %s WHERE workflow_id = ?};
53 0           my $data_field = $self->data_field;
54             my $select_data_fields
55 0           = ( ref $data_field )
56 0           ? join( ', ',
57             map { $self->handle->quote_identifier($_) } @{$data_field} )
58             : $self->handle->quote_identifier($data_field);
59             $sql = sprintf $sql, $select_data_fields,
60 0 0         $self->handle->quote_identifier( $self->table );
  0            
  0            
61             $self->log->debug( "Using SQL: ", $sql);
62 0           $self->log->debug( "Bind parameters: ", $wf->id );
63              
64 0           my ($sth);
65 0           eval {
66             $sth = $self->handle->prepare($sql);
67 0           $sth->execute( $wf->id );
68 0           };
69 0           if ($EVAL_ERROR) {
70 0           persist_error "Failed to retrieve extra data from table ",
71             $self->table, ": $EVAL_ERROR";
72 0 0         } else {
73 0           $self->log->debug("Prepared/executed extra data fetch ok");
74             my $row = $sth->fetchrow_arrayref;
75             if ( ref $data_field ) {
76 0           foreach my $i ( 0 .. $#{$data_field} ) {
77 0           $wf->context->param( $data_field->[$i], $row->[$i] );
78 0 0         $self->log->info(
79 0           sub { sprintf "Set data from %s.%s into context key %s ok",
  0            
80 0           $self->table, $data_field->[$i],
81             $data_field->[$i] } );
82 0     0     }
83             } else {
84 0           my $value = $row->[0];
85             $wf->context->param( $self->context_key, $value );
86             $self->log->info(
87 0           sub { sprintf "Set data from %s.%s into context key %s ok",
88 0           $self->table, $self->data_field,
89             $self->context_key } );
90 0     0     }
91             }
92 0           }
93              
94             1;
95              
96              
97             =pod
98              
99             =head1 NAME
100              
101             Workflow::Persister::DBI::ExtraData - Fetch extra data with each workflow and put it into the context
102              
103             =head1 VERSION
104              
105             This documentation describes version 1.60 of this package
106              
107             =head1 SYNOPSIS
108              
109             <persister name="MyPersister"
110             class="Workflow::Persister::DBI::ExtraData"
111             dsn="DBI:mysql:database=workflows"
112             user="wf"
113             password="mypass"
114             extra_table="workflow_ticket"
115             extra_data_field="ticket_id"
116             extra_context_key="ticket_id"/>
117              
118             =head1 DESCRIPTION
119              
120             =head2 Overview
121              
122             Simple subclass of L<Workflow::Persister::DBI> to allow you to declare
123             an extra table and data field(s) from which to fetch data whenever you
124             fetch a workflow. There is a simple restriction: the table must have a
125             field 'workflow_id' of the same datatype as the 'workflow_id' field in
126             the 'workflow' table.
127              
128             =head2 Examples
129              
130             # Specify a single field 'ticket_id' from the table 'workflow_ticket'
131             # and store it in the context using the same key:
132              
133             <persister
134             ...
135             extra_table="workflow_ticket"
136             extra_data_field="ticket_id"
137             ...
138              
139             # How you would use this:
140             my $wf = FACTORY->fetch_workflow( 'Ticket', 55 );
141             print "Workflow is associated with ticket: ",
142             $wf->context->param( 'ticket_id' );
143              
144             # Specify a single field 'ticket_id' from the table 'workflow_ticket'
145             # and store it in the context using a different key
146              
147             <persister
148             ...
149             extra_table="workflow_ticket"
150             extra_data_field="ticket_id"
151             extra_context_key="THE_TICKET_ID"
152             ...
153              
154             # How you would use this:
155             my $wf = FACTORY->fetch_workflow( 'Ticket', 55 );
156             print "Workflow is associated with ticket: ",
157             $wf->context->param( 'THE_TICKET_ID' );
158              
159             # Specify multiple fields ('ticket_id', 'last_viewer',
160             # 'last_view_date') to pull from the 'workflow_ticket' table:
161              
162             <persister
163             ...
164             extra_table="workflow_ticket"
165             extra_data_field="ticket_id,last_viewer,last_view_date"
166             ...
167              
168             # How you would use this:
169             my $wf = FACTORY->fetch_workflow( 'Ticket', 55 );
170             print "Workflow is associated with ticket: ",
171             $wf->context->param( 'ticket_id' ), " ",
172             "which was last viewed by ",
173             $wf->context->param( 'last_viewer' ), " on ",
174             $wf->context->param( 'last_view_date' );
175              
176             =head2 Configuration
177              
178             B<extra_table> (required)
179              
180             Table where the extra data are kept.
181              
182             B<extra_data_field> (required)
183              
184             Can be a single field or a comma-separated list of fields, all in the
185             same table. If a single field specified you have the option of
186             declaring a different C<extra_context_key> under which the value
187             should be stored in the workflow context. Otherwise the values are
188             stored by the field names in the workflow context.
189              
190             B<extra_context_key> (optional)
191              
192             Key under which to save the data from C<extra_data_field> in the
193             workflow context.
194              
195             Note: this is ignored when you specify multiple fields in
196             C<extra_data_field>; we just use the fieldnames for the context keys
197             in that case. And if you specify a single data field and do not
198             specify a context key we also use the data field name.
199              
200             =head2 METHODS
201              
202             =head3 init ( \%params )
203              
204             Initializes persister for extra workflow data.
205              
206             Throws L<Workflow::Exception> if initialization is not successful.
207              
208             =head3 fetch_extra_workflow_data ( $wf )
209              
210             Fetches extra data from database and feeds this to context of given workflow.
211              
212             Takes a single parameter, a workflow object to which extra data are feed if
213             retrieved successfully.
214              
215             Throws L<Workflow::Exception> if retrieval is not successful.
216              
217             =head1 COPYRIGHT
218              
219             Copyright (c) 2003-2022 Chris Winters. All rights reserved.
220              
221             This library is free software; you can redistribute it and/or modify
222             it under the same terms as Perl itself.
223              
224             Please see the F<LICENSE>
225              
226             =head1 AUTHORS
227              
228             Please see L<Workflow>
229              
230             =cut