File Coverage

blib/lib/Workflow/Persister/DBI/ExtraData.pm
Criterion Covered Total %
statement 17 58 29.3
branch 0 12 0.0
condition 0 5 0.0
subroutine 6 8 75.0
pod 2 2 100.0
total 25 85 29.4


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