1package App::Web; 2 3use strict; 4use vars qw($VERSION); 5use Log::Log4perl qw( get_logger ); 6use Workflow::Factory qw( FACTORY ); 7use XML::Simple qw( :strict ); 8 9$VERSION = '0.01'; 10 11my ( $log ); 12 13my %ACTION_DATA = (); 14my %DISPATCH = (); 15 16sub initialize_mappings { 17 my ( $class, $mapping_file ) = @_; 18 $log ||= get_logger(); 19 my %options = ( 20 ForceArray => [ 'url-mapping', 'action-display' ], 21 KeyAttr => [], 22 ); 23 my $config = XMLin( $mapping_file, %options ); 24 no strict 'refs'; 25 foreach my $url_map ( @{ $config->{'url-mapping'} } ) { 26 my $map_class = $url_map->{class}; 27 my $map_method = $url_map->{method}; 28 eval "require $map_class"; 29 if ( $@ ) { 30 die "Cannot include class '$map_class': $@\n"; 31 } 32 my $method = \&{ $map_class . '::' . $map_method }; 33 unless ( $method ) { 34 die "No method '$map_class->$map_method'\n"; 35 } 36 $DISPATCH{ $url_map->{url} } = $method; 37 } 38 39 foreach my $action_template ( @{ $config->{'action-display'} } ) { 40 $ACTION_DATA{ $action_template->{name} } = $action_template->{template}; 41 } 42 43 return $config; 44} 45 46 47######################################## 48# DISPATCH MAPPINGS 49# 50# Each of these routines returns a template name, stuffing data used 51# by the template into \%params and any outbound cookies into 52# \%cookies_out. 53 54sub lookup_dispatch { 55 my ( $class, $action_name ) = @_; 56 return $DISPATCH{ $action_name }; 57} 58 59sub create_workflow { 60 my ( $client, $request, $cookies_in, $cookies_out, $params ) = @_; 61 my $wf = FACTORY->create_workflow( 'Ticket' ); 62 $params->{workflow} = $wf; 63 $cookies_out->{workflow_id} = $wf->id; 64 return 'workflow_created.tmpl'; 65} 66 67sub fetch_workflow { 68 my ( $client, $request, $cookies_in, $cookies_out, $params ) = @_; 69 my $wf = _get_workflow( $params, $cookies_in ); 70 $cookies_out->{workflow_id} = $wf->id; 71 return 'workflow_fetched.tmpl'; 72} 73 74sub list_history { 75 my ( $client, $request, $cookies_in, $cookies_out, $params ) = @_; 76 my $wf = _get_workflow( $params, $cookies_in ); 77 my @history = $wf->get_history(); 78 $params->{history_list} = \@history; 79 return 'workflow_history.tmpl'; 80} 81 82sub execute_action { 83 my ( $client, $request, $cookies_in, $cookies_out, $params ) = @_; 84 my $wf = _get_workflow( $params, $cookies_in ); 85 86 my $action = $params->{action}; 87 unless ( $action ) { 88 die "To execute an action you must specify an action name!\n"; 89 } 90 91 # If they haven't entered data yet, add the fields (as a map) to 92 # the parameters and redirect to the form for entering it 93 94 unless ( $params->{_action_data_entered} || ! $ACTION_DATA{ $action } ) { 95 $params->{status_msg} = 96 "Action cannot be executed until you enter its data"; 97 my @fields = $wf->get_action_fields( $action ); 98 my %by_name = map { $_->name => $_ } @fields; 99 $params->{ACTION_FIELDS} = \%by_name; 100 return $ACTION_DATA{ $action }; 101 } 102 103 # Otherwise, set the user data directly into the workflow context... 104 $wf->context->param( $params ); 105 106 # ...and execute the action 107 eval { $wf->execute_action( $params->{action} ) }; 108 109 # ...if we catch a condition/validation exception, display the 110 # error and go back to the data entry form 111 112 if ( $@ && ( $@->isa( 'Workflow::Exception::Condition' ) || 113 $@->isa( 'Workflow::Exception::Validation' ) ) ) { 114 $log->error( "One or more conditions not met to execute action: $@; ", 115 "redirecting to form" ); 116 $params->{error_msg} = "Failed to execute action: $@"; 117 return $ACTION_DATA{ $action }; 118 } 119 $params->{status_msg} = "Action '$action' executed ok"; 120 return list_history( $client, $request, $cookies_in, $cookies_out, $params ); 121} 122 123sub login { 124 my ( $client, $request, $cookies_in, $cookies_out, $params ) = @_; 125 if ( $params->{current_user} ) { 126 $cookies_out->{current_user} = $params->{current_user}; 127 } 128 else { 129 $params->{error_msg} = "Please specify a login name I can use!"; 130 } 131 return 'index.tmpl'; 132} 133 134sub _get_workflow { 135 my ( $params, $cookies_in ) = @_; 136 return $params->{workflow} if ( $params->{workflow} ); 137 my $log = get_logger(); 138 my $wf_id = $params->{workflow_id} || $cookies_in->{workflow_id}; 139 unless ( $wf_id ) { 140 die "No workflow ID given! Please fetch a workflow or create ", 141 "a new one.\n"; 142 } 143 $log->debug( "Fetching workflow with ID '$wf_id'" ); 144 my $wf = FACTORY->fetch_workflow( 'Ticket', $wf_id ); 145 if ( $wf ) { 146 $log->debug( "Workflow found, current state is '", $wf->state, "'" ); 147 $params->{workflow} = $wf; 148 } 149 else { 150 $log->warn( "No workflow found with ID '$wf_id'" ); 151 die "No workflow found with ID '$wf_id'\n"; 152 } 153 return $wf; 154} 155 1561; 157