File Coverage

blib/lib/Form/Tiny.pm
Criterion Covered Total %
statement 92 92 100.0
branch 12 16 75.0
condition 10 10 100.0
subroutine 16 16 100.0
pod 0 2 0.0
total 130 136 95.5


line stmt bran cond sub pod time code
1             package Form::Tiny;
2             $Form::Tiny::VERSION = '2.21';
3 82     82   2811432 use v5.10;
  82         2163  
4 82     70   772 use strict;
  70         2327  
  70         2770  
5 70     66   609 use warnings;
  66         1454  
  66         2673  
6 66     51   485 use Carp qw(croak);
  51         96  
  51         2696  
7 51     51   23305 use Import::Into;
  51         112063  
  51         1583  
8              
9 51     51   18053 use Form::Tiny::Form;
  51         216  
  51         1918  
10 51     51   380 use Form::Tiny::Utils qw(:meta_handlers);
  51         120  
  51         17794  
11              
12             sub import
13             {
14 67     67   44707 my ($package, $caller) = (shift, scalar caller);
15              
16 67         508 my @wanted = (-base, @_);
17              
18             # very special case - do something UNLESS -nomoo was passed
19 67 100       355 unless ($package->_get_flag(\@wanted, -nomoo)) {
20 66         410 require Moo;
21 66         571 Moo->import::into($caller);
22             }
23              
24 67         34788 $package->ft_install($caller, @wanted);
25 67         45191 return;
26             }
27              
28             sub ft_install
29             {
30 67     67 0 282 my ($self, $caller, @import_flags) = @_;
31              
32 67         244 my $plugins_flag = $self->_get_flag(\@import_flags, 'plugins', 1);
33 67   100     263 my @plugins = ($self->_get_plugins(\@import_flags), @{$plugins_flag // []});
  67         428  
34              
35             # field context for form building
36 67         137 my $context;
37              
38 67         4440 my $wanted = $self->ft_run_plugins($caller, \$context, @plugins);
39              
40             # create metapackage with roles
41 67         159 my $meta = create_form_meta($caller, @{$wanted->{meta_roles}});
  67         347  
42 67         1490 $meta->set_form_roles($wanted->{roles});
43              
44             # install DSL
45             {
46 51     51   462 no strict 'refs';
  51         119  
  51         1986  
  67         1580  
47 51     51   364 no warnings 'redefine';
  51         115  
  51         34952  
48              
49 368         1672 *{"${caller}::$_"} = $wanted->{subs}{$_}
50 67         172 foreach keys %{$wanted->{subs}};
  67         420  
51             }
52              
53 67         565 return \$context;
54             }
55              
56             sub ft_run_plugins
57             {
58 121     121 0 344 my ($self, $caller, $context_ref, @plugins) = @_;
59              
60 121         467 my $wanted = {
61             subs => {},
62             roles => [],
63             meta_roles => [],
64             };
65              
66 121         234 my %seen;
67 121         308 foreach my $plugin (@plugins) {
68 124         386 $plugin = "Form::Tiny::Plugin::$plugin";
69 124         373 $plugin =~ s/^.+\+//;
70 124 100       600 next if $seen{$plugin}++;
71              
72 49     49   23709 my $success = eval "use $plugin; 1";
  49         169  
  49         833  
  114         7783  
73              
74 114 50       475 croak "could not load plugin $plugin: $@"
75             unless $success;
76 114 50       744 croak "$plugin is not a Form::Tiny::Plugin"
77             unless $plugin->isa('Form::Tiny::Plugin');
78              
79 114         494 $self->_merge_behaviors($wanted, $plugin->plugin($caller, $context_ref));
80             }
81              
82 121         429 return $wanted;
83             }
84              
85             sub _get_plugins
86             {
87 67     67   186 my ($self, $flags) = @_;
88              
89 67         436 my %known_flags = (
90             -base => ['Base'],
91             -strict => ['Strict'],
92             -filtered => ['Filtered'],
93              
94             # legacy no-op flags
95             -consistent => [],
96             );
97              
98 67         140 my @plugins;
99 67         184 foreach my $flag (@$flags) {
100             croak "no Form::Tiny import behavior for: $flag"
101 109 50       325 unless exists $known_flags{$flag};
102              
103 109         182 push @plugins, @{$known_flags{$flag}};
  109         331  
104             }
105              
106 67         304 return @plugins;
107             }
108              
109             sub _merge_behaviors
110             {
111 114     114   447 my ($self, $wanted, $behaviors) = @_;
112              
113 114   100     192 %{$wanted->{subs}} = (%{$wanted->{subs}}, %{$behaviors->{subs} // {}});
  114         467  
  114         356  
  114         603  
114 114   100     285 push @{$wanted->{roles}}, @{$behaviors->{roles} // []};
  114         235  
  114         530  
115 114   100     202 push @{$wanted->{meta_roles}}, @{$behaviors->{meta_roles} // []};
  114         219  
  114         841  
116             }
117              
118             sub _get_flag
119             {
120 134     134   385 my ($self, $flags, $wanted, $with_param) = @_;
121 134   100     693 $with_param //= 0;
122              
123 134         452 for my $n (0 .. $#$flags) {
124 232 100       756 if ($flags->[$n] eq $wanted) {
125 6         27 my $param = 1;
126 6 100       20 if ($with_param) {
127 5 50       16 croak "Form::Tiny flag $wanted needs a parameter"
128             if $n == $#$flags;
129 5         12 $param = $flags->[$n + 1];
130             }
131              
132 6         17 splice @$flags, $n, 1 + $with_param;
133 6         19 return $param;
134             }
135             }
136              
137 128         400 return;
138             }
139              
140             1;
141              
142             __END__