File Coverage

blib/lib/Workflow/Validator/InEnumeratedType.pm
Criterion Covered Total %
statement 35 35 100.0
branch 6 6 100.0
condition n/a
subroutine 10 10 100.0
pod 5 5 100.0
total 56 56 100.0


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