File Coverage

blib/lib/HTML/FormHandler/BuildPages.pm
Criterion Covered Total %
statement 97 135 71.8
branch 28 60 46.6
condition 8 17 47.0
subroutine 12 12 100.0
pod 0 2 0.0
total 145 226 64.1


line stmt bran cond sub pod time code
1             package HTML::FormHandler::BuildPages;
2             # ABSTRACT: used in Wizard
3             $HTML::FormHandler::BuildPages::VERSION = '0.40068';
4 1     1   795 use Moose::Role;
  1         3  
  1         8  
5 1     1   4844 use Try::Tiny;
  1         3  
  1         59  
6 1     1   6 use Class::Load qw/ load_optional_class /;
  1         2  
  1         38  
7 1     1   6 use namespace::autoclean;
  1         3  
  1         9  
8              
9             has 'page_list' => (
10             isa => 'ArrayRef',
11             is => 'rw',
12             traits => ['Array'],
13             default => sub { [] },
14             );
15              
16             sub has_page_list {
17 2     2 0 6 my ( $self ) = @_;
18              
19 2         34 my $page_list = $self->page_list;
20 2 50 33     25 return unless $page_list && ref $page_list eq 'ARRAY';
21 2 100       4 return $page_list if ( scalar @{$page_list} );
  2         9  
22 1         2 return;
23             }
24              
25             after '_build_fields' => sub {
26             my $self = shift;
27              
28             my $meta_plist = $self->_build_meta_page_list;
29             $self->_process_page_array( $meta_plist, 0 ) if $meta_plist;
30             my $plist = $self->has_page_list;
31             $self->_process_page_list($plist) if $plist;
32              
33             return unless $self->has_pages;
34             };
35              
36             sub _process_page_list {
37 1     1   4 my ( $self, $plist ) = @_;
38              
39 1 50       5 if ( ref $plist eq 'ARRAY' ) {
40 1         3 my @plist_copy = @{$plist};
  1         3  
41 1         7 $self->_process_page_array( $self->_array_pages( \@plist_copy ) );
42 1         5 return;
43             }
44 0         0 my %plist_copy = %{$plist};
  0         0  
45 0         0 $plist = \%plist_copy;
46             }
47              
48             sub _array_pages {
49 1     1   4 my ( $self, $pages ) = @_;
50              
51 1         2 my @new_pages;
52 1         11 while (@$pages) {
53 3         7 my $name = shift @$pages;
54 3         5 my $attr = shift @$pages;
55 3 50       11 unless ( ref $attr eq 'HASH' ) {
56 0         0 $attr = { type => $attr };
57             }
58 3         14 push @new_pages, { name => $name, %$attr };
59             }
60 1         8 return \@new_pages;
61             }
62              
63             sub _process_page_array {
64 2     2   6 my ( $self, $pages ) = @_;
65              
66 2         4 my $num_pages = scalar @$pages;
67 2         5 my $num_dots = 0;
68 2         5 my $count_pages = 0;
69 2         6 while ( $count_pages < $num_pages ) {
70 2         5 foreach my $page (@$pages) {
71 6         18 my $count = ( $page->{name} =~ tr/\.// );
72 6 50       16 next unless $count == $num_dots;
73 6         23 $self->_make_page($page);
74 6         14 $count_pages++;
75             }
76 2         9 $num_dots++;
77             }
78             }
79              
80             sub _make_page {
81 6     6   15 my ( $self, $page_attr ) = @_;
82              
83 6   50     31 $page_attr->{type} ||= 'Simple';
84 6         14 my $type = $page_attr->{type};
85 6         12 my $name = $page_attr->{name};
86 6 50       15 return unless $name;
87              
88 6         11 my $do_update;
89 6 50       20 if ( $name =~ /^\+(.*)/ ) {
90 0         0 $page_attr->{name} = $name = $1;
91 0         0 $do_update = 1;
92             }
93 6         11 my @page_name_space;
94 6         173 my $page_ns = $self->page_name_space;
95 6 50       15 if( $page_ns ) {
96 0 0       0 @page_name_space = ref $page_ns eq 'ARRAY' ? @$page_ns : $page_ns;
97             }
98 6         12 my @classes;
99             # '+'-prefixed fields could be full namespaces
100 6 50       19 if ( $type =~ s/^\+// )
101             {
102 0         0 push @classes, $type;
103             }
104 6         13 foreach my $ns ( @page_name_space, 'HTML::FormHandler::Page', 'HTML::FormHandlerX::Page' )
105             {
106 12         31 push @classes, $ns . "::" . $type;
107             }
108             # look for Page in possible namespaces
109 6         9 my $class;
110 6         12 foreach my $try ( @classes ) {
111 6 50       22 last if $class = load_optional_class($try) ? $try : undef;
    50          
112             }
113 6 50       260 die "Could not load page class '$type' for field '$name'"
114             unless $class;
115              
116 6 50       23 $page_attr->{form} = $self->form if $self->form;
117             # parent and name correction for names with dots
118 6 50 33     28 if ( $page_attr->{name} =~ /\./ ) {
    50          
119 0         0 my @names = split /\./, $page_attr->{name};
120 0         0 my $simple_name = pop @names;
121 0         0 my $parent_name = join '.', @names;
122 0         0 my $parent = $self->page($parent_name);
123 0 0       0 if ($parent) {
124 0         0 $page_attr->{parent} = $parent;
125 0         0 $page_attr->{name} = $simple_name;
126             }
127             }
128             elsif ( !( $self->form && $self == $self->form ) ) {
129             # set parent
130 0         0 $page_attr->{parent} = $self;
131             }
132 6   33     25 $self->_update_or_create_page( $page_attr->{parent} || $self->form,
133             $page_attr, $class, $do_update );
134             }
135              
136             sub _update_or_create_page {
137 6     6   18 my ( $self, $parent, $page_attr, $class, $do_update ) = @_;
138              
139 6         28 my $index = $parent->page_index( $page_attr->{name} );
140 6         11 my $page;
141 6 50       15 if ( defined $index ) {
142 0 0       0 if ($do_update) # this page started with '+'. Update.
143             {
144 0         0 $page = $parent->page( $page_attr->{name} );
145 0 0       0 die "Page to update for " . $page_attr->{name} . " not found"
146             unless $page;
147 0         0 delete $page_attr->{name};
148 0         0 foreach my $key ( keys %{$page_attr} ) {
  0         0  
149 0 0       0 $page->$key( $page_attr->{$key} )
150             if $page->can($key);
151             }
152             }
153             else # replace existing page
154             {
155 0         0 $page = $self->new_page_with_traits( $class, $page_attr);
156 0         0 $parent->set_page_at( $index, $page );
157             }
158             }
159             else # new page
160             {
161 6         22 $page = $self->new_page_with_traits( $class, $page_attr);
162 6         202 $parent->push_page($page);
163             }
164             }
165              
166             sub new_page_with_traits {
167 6     6 0 12 my ( $self, $class, $page_attr ) = @_;
168              
169 6         12 my $widget = $page_attr->{widget};
170 6         13 my $page;
171 6 50       15 unless( $widget ) {
172 6         24 my $attr = $class->meta->find_attribute_by_name( 'widget' );
173 6 50       534 if ( $attr ) {
174 0         0 $widget = $attr->default;
175             }
176             }
177 6         12 my @traits;
178 6 50       17 if( $page_attr->{traits} ) {
179 0         0 @traits = @{$page_attr->{traits}};
  0         0  
180 0         0 delete $page_attr->{traits};
181             }
182 6 50       18 if( $widget ) {
183 0         0 my $widget_role = $self->get_widget_role( $widget, 'Page' );
184 0         0 push @traits, $widget_role;
185             }
186 6 50       15 if( @traits ) {
187 0         0 $page = $class->new_with_traits( traits => \@traits, %{$page_attr} );
  0         0  
188             }
189             else {
190 6         9 $page = $class->new( %{$page_attr} );
  6         179  
191             }
192 6         6534 return $page;
193             }
194              
195             # loops through all inherited classes and composed roles
196             # to find pages specified with 'has_page'
197             sub _build_meta_page_list {
198 2     2   5 my $self = shift;
199 2         4 my @page_list;
200              
201 2         8 foreach my $sc ( reverse $self->meta->linearized_isa ) {
202 10         80 my $meta = $sc->meta;
203 10 50       167 if ( $meta->can('calculate_all_roles') ) {
204 10         29 foreach my $role ( reverse $meta->calculate_all_roles ) {
205 28 50 33     172 if ( $role->can('page_list') && $role->has_page_list ) {
206 0         0 foreach my $page_def ( @{ $role->page_list } ) {
  0         0  
207 0         0 my %new_page = %{$page_def}; # copy hashref
  0         0  
208 0         0 push @page_list, \%new_page;
209             }
210             }
211             }
212             }
213 10 100 100     300 if ( $meta->can('page_list') && $meta->has_page_list ) {
214 1         2 foreach my $page_def ( @{ $meta->page_list } ) {
  1         28  
215 3         5 my %new_page = %{$page_def}; # copy hashref
  3         11  
216 3         10 push @page_list, \%new_page;
217             }
218             }
219             }
220 2 100       9 return \@page_list if scalar @page_list;
221             }
222              
223             1;
224              
225             __END__
226              
227             =pod
228              
229             =encoding UTF-8
230              
231             =head1 NAME
232              
233             HTML::FormHandler::BuildPages - used in Wizard
234              
235             =head1 VERSION
236              
237             version 0.40068
238              
239             =head1 AUTHOR
240              
241             FormHandler Contributors - see HTML::FormHandler
242              
243             =head1 COPYRIGHT AND LICENSE
244              
245             This software is copyright (c) 2017 by Gerda Shank.
246              
247             This is free software; you can redistribute it and/or modify it under
248             the same terms as the Perl 5 programming language system itself.
249              
250             =cut