File Coverage

blib/lib/HTML/FormHandler/Blocks.pm
Criterion Covered Total %
statement 50 63 79.3
branch 11 24 45.8
condition 9 11 81.8
subroutine 10 11 90.9
pod 0 4 0.0
total 80 113 70.8


line stmt bran cond sub pod time code
1             package HTML::FormHandler::Blocks;
2             # ABSTRACT: arrange form layout using blocks
3             $HTML::FormHandler::Blocks::VERSION = '0.40067';
4              
5 141     141   80702 use Moose::Role;
  141         234  
  141         969  
6 141     141   494310 use Try::Tiny;
  141         237  
  141         9042  
7 141     141   598 use Class::Load qw/ load_optional_class /;
  141         202  
  141         5409  
8 141     141   579 use namespace::autoclean;
  141         197  
  141         1094  
9 141     141   8117 use Data::Clone;
  141         727  
  141         5628  
10 141     141   60922 use HTML::FormHandler::Widget::Block;
  141         355  
  141         90913  
11              
12             has 'blocks' => (
13             isa => 'HashRef[Object]',
14             is => 'ro',
15             lazy => 1,
16             traits => ['Hash'],
17             builder => 'build_blocks',
18             handles => {
19             has_blocks => 'count',
20             add_block => 'set',
21             block => 'get',
22             block_exists => 'exists',
23             },
24             );
25 9     9 0 250 sub build_blocks { {} }
26              
27             has 'block_list' => ( is => 'rw', isa => 'ArrayRef', lazy => 1, builder => 'build_block_list' );
28 241     241 0 5621 sub build_block_list {[]}
29              
30             has 'render_list' => (
31             is => 'rw',
32             isa => 'ArrayRef[Str]',
33             traits => ['Array'],
34             lazy => 1,
35             builder => 'build_render_list',
36             handles => {
37             has_render_list => 'count',
38             add_to_render_list => 'push',
39             all_render_list => 'elements',
40             get_render_list => 'get',
41             }
42             );
43              
44             sub get_renderer {
45 0     0 0 0 my ( $self, $name ) = @_;
46 0 0       0 die "must provide a name to get_renderer" unless $name;
47 0         0 my $obj = $self->block($name);
48 0 0       0 return $obj if ref $obj;
49 0         0 $obj = $self->field_from_index($name);
50 0 0       0 return $obj if ref $obj;
51 0         0 die "did not find a field or block with name $name\n";
52             }
53              
54             after '_build_fields' => sub {
55             my $self = shift;
56              
57             my $meta_blist = $self->_build_meta_block_list;
58             if( @$meta_blist ) {
59             foreach my $block_attr (@$meta_blist) {
60             $self->make_block($block_attr);
61             }
62             }
63             my $blist = $self->block_list;
64             if( @$blist ) {
65             foreach my $block_attr (@$blist) {
66             $self->make_block($block_attr);
67             }
68             }
69             };
70              
71             sub make_block {
72 20     20 0 30 my ( $self, $block_attr ) = @_;
73              
74 20   100     94 my $type = $block_attr->{type} ||= '';
75 20         34 my $name = $block_attr->{name};
76 20 50       39 die "You must supply a name for a block" unless $name;
77              
78 20         25 my $do_update;
79 20 50       57 if ( $name =~ /^\+(.*)/ ) {
80 0         0 $block_attr->{name} = $name = $1;
81 0         0 $do_update = 1;
82             }
83              
84 20         19 my $class;
85 20 100       47 if( $type ) {
86 4         25 $class = $self->get_widget_role($type, 'Block');
87             }
88             else {
89 16         20 $class = 'HTML::FormHandler::Widget::Block';
90             }
91              
92 20 50       5779 $block_attr->{form} = $self->form if $self->form;
93              
94 20         46 my $block = $self->form->block( $block_attr->{name} );
95 20 50 33     56 if ( defined $block && $do_update ) {
96 0         0 delete $block_attr->{name};
97 0         0 foreach my $key ( keys %{$block_attr} ) {
  0         0  
98 0 0       0 $block->$key( $block_attr->{$key} )
99             if $block->can($key);
100             }
101             }
102             else # new block
103             {
104 20         175 $block = $class->new(%$block_attr);
105 20         18201 $self->add_block( $name, $block );
106             }
107             }
108              
109             # loops through all inherited classes and composed roles
110             # to find blocks specified with 'has_block'
111             sub _build_meta_block_list {
112 243     243   386 my $self = shift;
113 243         377 my @block_list;
114              
115 243         1066 foreach my $sc ( reverse $self->meta->linearized_isa ) {
116 980         8492 my $meta = $sc->meta;
117 980 50       12981 if ( $meta->can('calculate_all_roles') ) {
118 980         2224 foreach my $role ( reverse $meta->calculate_all_roles ) {
119 2744 100 100     18264 if ( $role->can('block_list') && $role->has_block_list ) {
120 1         2 foreach my $block_def ( @{ $role->block_list } ) {
  1         27  
121 3         5 push @block_list, $block_def;
122             }
123             }
124             }
125             }
126 980 100 100     27804 if ( $meta->can('block_list') && $meta->has_block_list ) {
127 6         6 foreach my $block_def ( @{ $meta->block_list } ) {
  6         168  
128 11         22 push @block_list, $block_def;
129             }
130             }
131             }
132 243         2360 return clone( \@block_list );
133             }
134              
135              
136             1;
137              
138             __END__
139              
140             =pod
141              
142             =encoding UTF-8
143              
144             =head1 NAME
145              
146             HTML::FormHandler::Blocks - arrange form layout using blocks
147              
148             =head1 VERSION
149              
150             version 0.40067
151              
152             =head1 SYNOPSIS
153              
154             This is a role which provides the ability to render your form in
155             arbitrary 'blocks', instead of by fields. This role is included
156             by default in HTML::FormHandler.
157              
158             package MyApp::Form;
159             use HTML::FormHandler::Moose;
160             extends 'HTML::FormHandler';
161              
162             sub build_render_list {[ 'foo', 'fset' ]}
163             has_field 'foo';
164             has_field 'bar';
165             has_field 'nox';
166             has_block 'fset' => ( tag => 'fieldset', render_list => ['bar', 'nox'] );;
167             ....
168             $form->render;
169              
170             Blocks live in the HTML::FormHandler::Widget::Block:: namespace. The default,
171             non-typed block is L<HTML::FormHandler::Widget::Block>. Provide a type for
172             custom blocks:
173              
174             has_block 'my_block' => ( type => 'CustomBlock', render_list => [...] );
175              
176             You can also build blocks with a 'block_list' attribute, or the builder for it,
177             'build_block_list'.
178              
179             Rendering with blocks is supported by the rendering widgets. Render::Simple doesn't
180             do it, though it would be possible to make your own custom renderer.
181              
182             =head1 AUTHOR
183              
184             FormHandler Contributors - see HTML::FormHandler
185              
186             =head1 COPYRIGHT AND LICENSE
187              
188             This software is copyright (c) 2016 by Gerda Shank.
189              
190             This is free software; you can redistribute it and/or modify it under
191             the same terms as the Perl 5 programming language system itself.
192              
193             =cut