File Coverage

blib/lib/Catmandu/Fix/Bind/each.pm
Criterion Covered Total %
statement 26 26 100.0
branch 2 2 100.0
condition 2 3 66.6
subroutine 8 8 100.0
pod 0 1 0.0
total 38 40 95.0


line stmt bran cond sub pod time code
1             package Catmandu::Fix::Bind::each;
2              
3             our $VERSION = '1.2020';
4              
5 1     1   1134 use strict;
  1         4  
  1         36  
6 1     1   4 use warnings;
  1         3  
  1         24  
7              
8 1     1   5 use Catmandu::Sane;
  1         2  
  1         10  
9 1     1   8 use Moo;
  1         2  
  1         43  
10              
11 1     1   418 use Catmandu::Util;
  1         3  
  1         48  
12 1     1   469 use Catmandu::Fix::Has;
  1         2  
  1         6  
13 1     1   343 use Carp;
  1         2  
  1         570  
14              
15             with 'Catmandu::Fix::Bind', 'Catmandu::Fix::Bind::Group';
16              
17             has path => (fix_opt => 1);
18             has var => (fix_opt => 1);
19              
20             has _root_ => (is => 'rw');
21              
22             sub unit {
23 13     13 0 29 my ($self, $data) = @_;
24              
25 13         43 $self->_root_($data);
26              
27 13 100 66     79 if ($self->path && $self->path ne '.') {
28 2         14 return Catmandu::Util::data_at($self->path, $data);
29             }
30             else {
31 11         202 return $data;
32             }
33             }
34              
35             sub bind {
36             my ($self, $data, $code) = @_;
37              
38             if (!Catmandu::Util::is_hash_ref($data)) {
39             $code->($data);
40             }
41             else {
42             my @keys = sort keys %{$data};
43             for my $key (@keys) {
44             my $value = $data->{$key};
45             my $scope;
46              
47             if ($self->var) {
48             $scope = $self->_root_;
49              
50             $scope->{$self->var} = {'key' => $key, 'value' => $value};
51             }
52             else {
53             $scope = $data;
54             $scope->{'key'} = $key;
55             $scope->{'value'} = $value;
56             }
57              
58             $code->($scope);
59              
60             if ($self->var) {
61              
62             # Key and values can be updated
63             if (my $mkey = $scope->{$self->var}->{key}) {
64             $data->{$mkey} = $scope->{$self->var}->{value};
65             if ($mkey ne $key) {
66             delete $data->{$key};
67             }
68             }
69              
70             delete $scope->{$self->var};
71             }
72             else {
73             if (my $mkey = $scope->{key}) {
74             $data->{$mkey} = $scope->{value};
75             if ($mkey ne $key) {
76             delete $data->{$key};
77             }
78             }
79              
80             delete $scope->{'key'};
81             delete $scope->{'value'};
82             }
83             }
84             }
85              
86             return $data;
87             }
88              
89             1;
90             __END__
91              
92             =pod
93              
94             =head1 NAME
95              
96             Catmandu::Fix::Bind::each - a binder that executes fixes for every (key, value) pair in a hash
97              
98             =head1 SYNOPSIS
99              
100             # Create a hash:
101             # demo:
102             # nl: 'Tuin der lusten'
103             # en: 'The Garden of Earthly Delights'
104              
105             # Create a list of all the titles, without the language tags.
106             do each(path: demo, var: t)
107             copy_field(t.value, titles.$append)
108             end
109              
110             # This will result in:
111             # demo:
112             # nl: 'Tuin der lusten'
113             # en: 'The Garden of Earthly Delights'
114             # titles:
115             # - 'Tuin der lusten'
116             # - 'The Garden of Earthly Delights'
117              
118             # Upcase every key in the root hash
119             # foo: bar
120             # test: 1234
121             do each(path:., var: t)
122             upcase(t.key)
123             end
124              
125             # This will result in
126             # FOO: bar
127             # TEST: 1234
128              
129             =head1 DESCRIPTION
130              
131             The each binder will iterate over a hash and return a (key, value)
132             pair (see the Perl L<each|http://perldoc.perl.org/functions/each.html> function
133             for the inspiration for this bind) and execute all fixes for each pair.
134              
135             The bind always returns a C<var.key> and C<var.value> pair which can be used
136             in the fixes.
137              
138             =head1 CONFIGURATION
139              
140             =head2 path
141              
142             The path to a hash in the data.
143              
144             =head2 var
145              
146             The temporary field that will be created in the root of the record
147             containing a C<key> and C<value> field containing the I<key> and
148             I<value> of the iterated data.
149              
150             =head1 AUTHOR
151              
152             Pieter De Praetere, C<< pieter.de.praetere at helptux.be >>
153              
154             =head1 SEE ALSO
155              
156             L<Catmandu::Fix::Bind::list>
157             L<Catmandu::Fix::Bind>
158              
159             =cut