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