File Coverage

lib/Workflow/Validator/InEnumeratedType.pm
Criterion Covered Total %
statement 32 32 100.0
branch 6 6 100.0
condition n/a
subroutine 9 9 100.0
pod 4 4 100.0
total 51 51 100.0


line stmt bran cond sub pod time code
1              
2             use warnings;
3 1     1   535 use strict;
  1         1  
  1         28  
4 1     1   4 use base qw( Workflow::Validator );
  1         2  
  1         42  
5 1     1   7 use Workflow::Exception qw( configuration_error validation_error );
  1         2  
  1         303  
6 1     1   272  
  1         3  
  1         374  
7             $Workflow::Validator::InEnumeratedType::VERSION = '1.61';
8              
9             my ( $self, $params ) = @_;
10             $self->{_enum} = [];
11 3     3   4 $self->{_enum_match} = {};
12 3         6 unless ( $params->{value} ) {
13 3         3 configuration_error "Validator 'InEnumeratedType' must be ",
14 3 100       7 "initialized with the values you wish to ",
15 1         2 "validate against using the parameter 'value'.";
16             }
17             my @values
18             = ( ref $params->{value} eq 'ARRAY' )
19             ? @{ $params->{value} }
20             : ( $params->{value} );
21 1         2 $self->add_enumerated_values(@values);
22 2 100       6 }
23 2         4  
24             my ( $self, $wf, $value ) = @_;
25             unless ( $self->is_enumerated_value($value) ) {
26             validation_error "Value '$value' must be one of: ", join ", ",
27 2     2 1 49 $self->get_enumerated_values;
28 2 100       4 }
29 1         4 }
30              
31             my ( $self, @values ) = @_;
32             push @{ $self->{_enum} }, @values;
33             $self->{_enum_match}{$_} = 1 for (@values);
34             }
35 3     3 1 9  
36 3         4 my ($self) = @_;
  3         6  
37 3         11 return @{ $self->{_enum} };
38             }
39              
40             my ( $self, $value ) = @_;
41 4     4 1 7 return $self->{_enum_match}{$value};
42 4         4 }
  4         22  
43              
44             1;
45              
46 4     4 1 7  
47 4         15 =pod
48              
49             =head1 NAME
50              
51             Workflow::Validator::InEnumeratedType - Ensure a value is one of a declared set of values
52              
53             =head1 VERSION
54              
55             This documentation describes version 1.61 of this package
56              
57             =head1 SYNOPSIS
58              
59             # Inline the enumeration...
60              
61             <action name="PlayGame">
62             <validator name="InEnumeratedType">
63             <value>Rock</value>
64             <value>Scissors</value>
65             <value>Paper</value>
66             <arg value="$play"/>
67             </validator>
68             </action>
69              
70             # Or declare it in the validator to be more readable...
71             <validator name="RSP"
72             class="Validator::InEnumeratedType">
73             <value>Rock</value>
74             <value>Scissors</value>
75             <value>Paper</value>
76             </validator>
77              
78             # ...and use it in your action
79             <action name="PlayGame">
80             <validator name="RSP">
81             <arg value="$play"/>
82             </validator>
83             </action>
84              
85             =head1 DESCRIPTION
86              
87             This validator ensures that a value matches one of a set of
88             values. You declare the values in the set (or enumerated type) in
89             either the main validator declaration or in the declaration inside the
90             action, then pass a single argument of the value in the context you
91             would like to check.
92              
93             Declaring the members of the enumerated type in the validator
94             configuration makes for more readable (and brief) action
95             configurations, as well as making the types more reusable, but it is
96             really up to you.
97              
98             =head1 SUBCLASSING
99              
100             =head2 Strategy
101              
102             Unlike some other validator classes this one is setup to be
103             subclassable. It is usable as-is, of course, but many times you will
104             find that you have need of more interesting types in your enumeration
105             than simple strings. So this class provides the hooks for you to
106             simply create your own.
107              
108             For instance, in a trouble ticket system you may have the idea that
109             tickets can only be assigned to particular users. Maybe they are in a
110             'worker' role, maybe they are some administrators, whatever. By
111             creating a class to have these users as an enumerated type, combined
112             with declaring the required Action fields, you make for a pretty
113             powerful piece of reflection.
114              
115             Onto the code. First we declare a field type of 'worker':
116              
117             <field type="worker"
118             class="MyApp::Field::Worker"/>
119              
120             Next a validator of this enumerated type:
121              
122             <validator name="IsWorker"
123             class="MyApp::Validator::WorkerEnumeration"/>
124              
125             We then associate this field type with a field in the action and the
126             validator to ensure the user selects a worker from the right pool:
127              
128             <action name="AssignTicket">
129             <field name="assignee"
130             type="worker"
131             is_required="yes"/>
132             ...
133             <validator name="IsWorker">
134             <arg value="$assignee"/>
135             </validator>
136              
137             Note that the name of the field and the name used in the validator are
138             the same. This allows external applications to query the action for
139             its fields, get 'assignee' as the name and get a list of User objects
140             (or something similar) as the types from which to choose a value, and
141             checks that same field to ensure a correct choice was submitted.
142              
143             The implementation for the validator might look like:
144              
145             package MyApp::Validator::WorkerEnumeration;
146              
147             sub validate {
148             my ( $self, $wf, $worker_id ) = @_;
149             my $ticket = $context->param( 'ticket' );
150             unless ( $ticket ) {
151             my $ticket_id = $context->param( 'ticket_id' );
152             $ticket = Ticket->fetch( $ticket_id );
153             }
154             my $workers = $ticket->fetch_available_workers();
155             my @worker_id = map { $_->id } @{ $workers };
156             $self->add_enumerated_values( @worker_id );
157             $self->SUPER::validate( $wf, $worker_id );
158             }
159              
160             =head2 METHODS
161              
162             =head3 _init( \%params )
163              
164             This method initializes the class and the enumerated class.
165              
166             It uses L</add_enumerated_values> to add the set of values for enumeration.
167              
168             The primary parameter is value, which should be used to specify the
169             either a single value or a reference to array of values to be added.
170              
171             =head3 validate
172              
173             The validate method is the public API. It encapulates L</is_enumerated:value>
174             and works with L<Workflow>.
175              
176             =head3 add_enumerated_values( @values )
177              
178             This method ads an array of values to be regarded as enumerations for the
179             validator.
180              
181             =head3 get_enumerated_values()
182              
183             This method returns the defined enumerated values for the class as an array.
184              
185             =head3 is_enumerated_value( $value )
186              
187             This is most often the single method you will want to modify.
188              
189             The method offers assertion of a given value, as to whether it is an enumerated
190             type as defined in the class.
191              
192             =head1 EXCEPTIONS
193              
194             =over
195              
196             =item * Validator 'InEnumeratedType' must be initialized with the values you wish to validate against using the parameter 'value'.
197              
198             This L<Workflow::Exception> is thrown from L</_init> if the 'value'
199             parameter is not set.
200              
201             =item * Value '$value' must be one of: <@values>
202              
203             This L<Workflow::Exception> is thrown from L</_validator> if the value
204             to be asserted is not mathing any of the enumerated values defined as
205             part of the set.
206              
207             =back
208              
209             =head1 COPYRIGHT
210              
211             Copyright (c) 2003-2022 Chris Winters. All rights reserved.
212              
213             This library is free software; you can redistribute it and/or modify
214             it under the same terms as Perl itself.
215              
216             Please see the F<LICENSE>
217              
218             =head1 AUTHORS
219              
220             Please see L<Workflow>
221              
222             =cut