File Coverage

blib/lib/Brick/Result.pm
Criterion Covered Total %
statement 18 105 17.1
branch 0 42 0.0
condition 0 6 0.0
subroutine 6 12 50.0
pod 6 6 100.0
total 30 171 17.5


line stmt bran cond sub pod time code
1             package Brick::Result;
2 2     2   2613 use strict;
  2         4  
  2         79  
3              
4 2     2   9 use vars qw($VERSION);
  2         2  
  2         100  
5              
6 2     2   10 use Carp qw(carp croak);
  2         3  
  2         204  
7              
8             $VERSION = '0.905';
9              
10             =encoding utf8
11              
12             =head1 NAME
13              
14             Brick::Result - the result of applying a profile
15              
16             =head1 SYNOPSIS
17              
18             use Brick;
19              
20             my $result = $brick->apply( $Profile, $Input );
21              
22             $result->explain;
23              
24             =head1 DESCRIPTION
25              
26             This class provides methods to turn the data structure returned
27             by apply() into a useable form for particular situations.
28              
29              
30             =head2 Class methods
31              
32             =over 4
33              
34             =item result_item_class
35              
36             Loads and returns the class name to use for the elements of the Results
37             data structure.
38              
39             =cut
40              
41 0     0 1   sub result_item_class { require Brick::Result::Item; 'Brick::Result::Item' };
  0            
42              
43             =back
44              
45             =head2 Instance methods
46              
47             =over
48              
49             =item explain
50              
51             Create a string the shows the result in an outline form.
52              
53             =cut
54              
55              
56             # for the $pair thing in explain
57 2     2   12 use constant LEVEL => 0;
  2         3  
  2         170  
58 2     2   10 use constant MESSAGE => 1;
  2         40  
  2         534  
59              
60              
61             sub explain {
62 0     0 1   my( $result_set ) = @_;
63              
64 0           my $str = '';
65              
66 0           foreach my $element ( @$result_set ) {
67 0           my $level = 0;
68              
69 0           $str .= "$$element[0]: " . do {
70 0 0         if( $element->passed ) { "passed " }
  0 0          
    0          
71 0           elsif( $element->is_validation_error ) { "failed " }
72 0           elsif( $element->is_code_error ) { "code error in " }
73             };
74              
75 0           $str .= $element->get_method() . "\n";
76              
77 0 0         if( $element->passed ) {
78 0           $str .= "\n";
79 0           next;
80             }
81              
82             # this descends into the error tree (without using recursion
83 0           my @uses = ( [ $level, $element->get_messages ] );
84              
85 0           while( my $pair = shift @uses ) {
86             # is it a single error or a composition?
87 0 0         if( ! ref $pair->[ MESSAGE ] ) {
    0          
    0          
88 0           $str .= $pair->[ MESSAGE ] . "foo";
89             }
90             elsif( ! ref $pair->[ MESSAGE ] eq ref {} ) {
91 0           next;
92             }
93             elsif( exists $pair->[ MESSAGE ]->{errors} ) {
94             # something else to process, but put it back into @uses
95             unshift @uses, map {
96 0           [ $pair->[ LEVEL ] + 1, $_ ]
97 0           } @{ $pair->[ MESSAGE ]->{errors} };
  0            
98             }
99             else {
100             # this could come back as an array ref instead of a string
101 2     2   12 no warnings 'uninitialized';
  2         3  
  2         1682  
102             $str .= "\t" . #x $pair->[ LEVEL ] .
103 0           join( ": ", @{ $pair->[ MESSAGE ]
104 0           }{qw(failed_field handler message)} ) . "\n";
105             }
106              
107             }
108              
109 0           $str.= "\n";
110             }
111              
112 0           $str;
113             }
114              
115             =item flatten
116              
117             Collapse the result structure to an array of flat hashes.
118              
119             =cut
120              
121             sub flatten {
122 0     0 1   my( $result_set ) = @_;
123              
124 0           my $str = '';
125              
126 0           my @flatten;
127              
128 0           foreach my $element ( @$result_set ) { # one element per profile element
129 0           bless $element, $result_set->result_item_class;
130 0 0         next if $element->passed;
131 0           my $constraint = $element->get_method;
132              
133 0           my @uses = ( $element->get_messages );
134              
135 0           while( my $hash = shift @uses ) {
136 0 0         if( ! ref $hash eq ref {} ) {
137 0           carp "Non-hash reference in messages result key! Skipping";
138 0           next;
139             }
140              
141             # is it a single error or a composition?
142 0 0         unless( ref $hash ) {
    0          
143 0           next;
144             }
145 0           elsif( exists $hash->{errors} ) {
146 0           unshift @uses, @{ $hash->{errors} };
  0            
147             }
148             else {
149 0           push @flatten, { %$hash, constraint => $constraint };
150             }
151             }
152             }
153              
154 0           \@flatten;
155             }
156              
157             =item flatten_by_field
158              
159             Similar to flatten, but keyed by the field that failed the constraint.
160              
161             =cut
162              
163             sub flatten_by_field {
164 0     0 1   my( $result_set ) = @_;
165              
166 0           my $str = '';
167              
168 0           my %flatten;
169             my %Seen;
170              
171 0           foreach my $element ( @$result_set ) { # one element per profile element
172 0 0         next if $element->passed;
173 0           my $constraint = $element->get_method;
174              
175 0           my @uses = ( $element->get_messages );
176              
177 0           while( my $hash = shift @uses ) {
178             # is it a single error or a composition?
179 0 0         unless( ref $hash ) {
    0          
180 0           next;
181             }
182 0           elsif( exists $hash->{errors} ) {
183 0           unshift @uses, @{ $hash->{errors} };
  0            
184             }
185             else {
186 0           my $field = $hash->{failed_field};
187 0 0 0       next if $hash->{handler} and $Seen{$field}{$hash->{handler}}++;
188 0 0         $flatten{ $field } = [] unless exists $flatten{ $field };
189 0           push @{ $flatten{ $field } },
  0            
190             { %$hash, constraint => $constraint };
191 0           $Seen{$field}{$hash->{handler}}++;
192             }
193             }
194             }
195              
196 0           \%flatten;
197             }
198              
199             =item flatten_by
200              
201             Similar to flatten, but keyed by the hash key named in the argument list.
202              
203             =cut
204              
205             sub flatten_by {
206 0     0 1   my( $result_set, $key ) = @_;
207              
208 0           my $str = '';
209              
210 0           my %flatten;
211             my %Seen;
212              
213 0           foreach my $element ( @$result_set ) { # one element per profile element
214 0 0         next if $element->passed;
215 0           my $constraint = $element->get_method;
216              
217 0           my @uses = ( $element->get_messages );
218              
219 0           while( my $hash = shift @uses ) {
220             # is it a single error or a composition?
221 0 0         unless( ref $hash ) {
    0          
222 0           next;
223             }
224 0           elsif( exists $hash->{errors} ) {
225 0           unshift @uses, @{ $hash->{errors} };
  0            
226             }
227             else {
228 0           my $field = $hash->{$key};
229 0 0 0       next if $hash->{handler} and $Seen{$field}{$hash->{handler}}++;
230 0 0         $flatten{ $field } = [] unless exists $flatten{ $field };
231 0           push @{ $flatten{ $field } },
  0            
232             { %$hash, constraint => $constraint };
233 0           $Seen{$field}{$hash->{handler}}++;
234             }
235             }
236             }
237              
238 0           \%flatten;
239             }
240              
241             =item dump
242              
243             What should this do?
244              
245             =cut
246              
247 0     0 1   sub dump { croak "Not yet implemented" }
248              
249             =back
250              
251             =head1 TO DO
252              
253             TBA
254              
255             =head1 SEE ALSO
256              
257             L, L
258              
259             =head1 SOURCE AVAILABILITY
260              
261             This source is in Github:
262              
263             https://github.com/briandfoy/brick
264              
265             =head1 AUTHOR
266              
267             brian d foy, C<< >>
268              
269             =head1 COPYRIGHT
270              
271             Copyright © 2007-2026, brian d foy . All rights reserved.
272              
273             You may redistribute this under the terms of the Artistic License 2.0.
274              
275             =cut
276              
277             1;