File Coverage

blib/lib/MooseX/App/Exporter.pm
Criterion Covered Total %
statement 127 135 94.0
branch 22 34 64.7
condition 9 15 60.0
subroutine 23 26 88.4
pod 0 13 0.0
total 181 223 81.1


line stmt bran cond sub pod time code
1             # ============================================================================
2             package MooseX::App::Exporter;
3             # ============================================================================
4              
5 15     15   351 use 5.010;
  15         57  
6 15     15   85 use utf8;
  15         31  
  15         117  
7 15     15   403 use strict;
  15         31  
  15         318  
8 15     15   78 use warnings;
  15         119  
  15         485  
9              
10 15     15   96 use Moose::Exporter;
  15         30  
  15         104  
11 15     15   7160 use MooseX::App::Utils;
  15         60  
  15         706  
12 15     15   7961 use MooseX::App::ParsedArgv;
  15         66  
  15         751  
13 15     15   138 use List::Util qw(first);
  15         34  
  15         24242  
14              
15             my %PLUGIN_SPEC;
16              
17             sub import {
18 36     36   5991 my ( $class, @imports ) = @_;
19              
20 36         145 my $caller_class = caller();
21              
22 36         1108 my $caller_stash = Package::Stash->new($caller_class);
23 36         251 my $exporter_stash = Package::Stash->new(__PACKAGE__);
24              
25 36         128 foreach my $import (@imports) {
26 246         1173 my $symbol = $exporter_stash->get_symbol('&'.$import);
27 246 50       648 Carp::confess(sprintf('Symbol %s not defined in %s',$import,__PACKAGE__))
28             unless defined $symbol;
29 246         1540 $caller_stash->add_symbol('&'.$import, $symbol);
30             }
31              
32 36         1312 return;
33             }
34              
35             sub parameter {
36 15     15 0 24496 my ($meta,$name,@rest) = @_;
37 15         55 return _handle_attribute($meta,$name,'parameter',@rest);
38             }
39              
40             sub option {
41 102     102 0 121499 my ($meta,$name,@rest) = @_;
42 102         392 return _handle_attribute($meta,$name,'option',@rest);
43             }
44              
45             sub _handle_attribute {
46 117     117   379 my ($meta,$name,$type,@rest) = @_;
47              
48 117 50       447 Moose->throw_error('Usage: option \'name\' => ( key => value, ... )')
49             if @rest % 2 == 1;
50              
51 117         216 my %info;
52 117         422 @info{qw(package file line)} = caller(2);
53              
54 117         3233 my %attributes = ( definition_context => \%info, @rest );
55 117 100       509 my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
56              
57             # We are in a command class
58 117 100 100     5198 if (! $meta->isa('Moose::Meta::Role')
59             && $meta->meta->does_role('MooseX::App::Meta::Role::Class::Command')) {
60              
61             # Get required extra traits for this class on first attrubute
62 88 100       29339 unless ($meta->has_app_attribute_metaroles) {
63             # Find MooseX::App::Meta::Role::Class::Base in ISA
64 28         158 foreach my $parent ($meta->linearized_isa) {
65 91 50       24533 if ($parent->meta->does_role('MooseX::App::Meta::Role::Class::Base')) {
66 0         0 $meta->app_attribute_metaroles([]);
67 0         0 last;
68             }
69             }
70             # Apply missing meta roles if required to do so
71 28 50       4568 unless ($meta->has_app_attribute_metaroles) {
72 28         79 my @extra_classes;
73 28         135 my $name = $meta->name;
74 28         142 foreach my $class (keys %PLUGIN_SPEC) {
75 31         192 my @commands = $class->meta->command_classes;
76 31 100   100   414 if (first { $name eq $_ } @commands) {
  100         220  
77 28         117 my $attribute_metaclass = $class->meta->attribute_metaclass;
78             push @extra_classes,
79 4         23 map { $_->name }
80 34         261 grep { $_->name ne 'MooseX::App::Meta::Role::Attribute::Option' }
81 36         189 grep { ! $_->isa('Moose::Meta::Role::Composite') }
82             map {
83 28 100       636 $_->isa('Moose::Meta::Role::Composite') ?
  32         6286  
84             $_->calculate_all_roles : $_
85             }
86             $attribute_metaclass->meta->calculate_all_roles_with_inheritance;
87             }
88             }
89              
90 28         1396 $meta->app_attribute_metaroles_add(@extra_classes);
91             }
92             }
93              
94 88   50     553 $attributes{traits} ||= [];
95 88         145 push(@{$attributes{traits}},$meta->app_attribute_metaroles_uniq);
  88         3997  
96             }
97              
98 117         13184 $attributes{'cmd_type'} = $type;
99             # Loop all attributes and check attribute traits
100 117         297 foreach my $attr (@$attrs) {
101 119         5074 my %local_attributes = %attributes;
102 119 100       457 if ($attr =~ m/^\+(.+)/) {
103 1         13 my $meta_attribute = $meta->find_attribute_by_name($1);
104 1 50       73 unless ($meta_attribute->does('MooseX::App::Meta::Role::Attribute::Option')) {
105 1   50     131 $local_attributes{traits} ||= [];
106 1         4 push @{$local_attributes{traits}},'MooseX::App::Meta::Role::Attribute::Option'
107 0 0   0   0 unless (first { $_ eq 'AppOption' || $_ eq 'MooseX::App::Meta::Role::Attribute::Option' }
108 1 50       6 @{$local_attributes{traits}});
  1         8  
109             }
110             }
111              
112 119         591 $meta->add_attribute($attr, %local_attributes);
113             }
114              
115 117         397399 return;
116             }
117              
118             sub app_prefer_commandline($) {
119 4     4 0 79 my ( $meta, $value ) = @_;
120 4         158 return $meta->app_prefer_commandline($value);
121             }
122              
123             sub app_strict($) {
124 4     4 0 18868 my ( $meta, $value ) = @_;
125 4         210 return $meta->app_strict($value);
126             }
127              
128             sub app_fuzzy($) {
129 1     1 0 4324 my ( $meta, $value ) = @_;
130 1         47 return $meta->app_fuzzy($value);
131             }
132              
133             sub app_permute($) {
134 3     3 0 13484 my ( $meta, $value ) = @_;
135 3         143 return $meta->app_permute($value);
136             }
137              
138             sub app_base($) {
139 3     3 0 52 my ( $meta, $name ) = @_;
140 3         111 return $meta->app_base($name);
141             }
142              
143             sub process_plugins {
144 17     17 0 74 my ($self,$caller_class,@plugins) = @_;
145              
146             # Loop all requested plugins
147 17         94 my @plugin_classes;
148 17         52 foreach my $plugin (@plugins) {
149 15         52 my $plugin_class = 'MooseX::App::Plugin::'.$plugin;
150              
151             # TODO eval plugin class
152 15         85 Class::Load::load_class($plugin_class);
153              
154 15         475 push (@plugin_classes,$plugin_class);
155             }
156              
157             # Store plugin spec
158 17         75 $PLUGIN_SPEC{$caller_class} = \@plugin_classes;
159 17         81 return;
160             }
161              
162             sub process_init_meta {
163 17     17 0 91 my ($self,%args) = @_;
164              
165 17         118 Moose->init_meta( %args );
166              
167 17   50     58276 my $plugins = $PLUGIN_SPEC{$args{for_class}} || [];
168 17   50     84 my $apply_metaroles = delete $args{metaroles} || {};
169 17   50     71 my $apply_roles = delete $args{roles} || [];
170              
171             # Add plugin roles
172 17         65 foreach my $plugin (@$plugins) {
173 15         30 push(@{$apply_roles},$plugin,{ -excludes => [ 'plugin_metaroles' ] } )
  15         79  
174             }
175              
176             # Add common role
177 17         63 push(@{$apply_roles},'MooseX::App::Role::Common')
178 17 50   47   102 unless first { $_ eq 'MooseX::App::Role::Common' } @{$apply_roles};
  47         130  
  17         452  
179              
180             # Process all plugins in the given order
181 17         63 foreach my $plugin_class (@{$plugins}) {
  17         50  
182 15 50       361 if ($plugin_class->can('plugin_metaroles')) {
183 15         102 my ($metaroles) = $plugin_class->plugin_metaroles($args{for_class});
184 15 50       72 if (ref $metaroles eq 'HASH') {
185 15         61 foreach my $type (keys %$metaroles) {
186 19   50     61 $apply_metaroles->{$type} ||= [];
187 19         33 push (@{$apply_metaroles->{$type}},@{$metaroles->{$type}});
  19         42  
  19         74  
188             }
189             }
190             }
191             }
192              
193             # Add meta roles
194             Moose::Util::MetaRole::apply_metaroles(
195             for => $args{for_class},
196 17         145 class_metaroles => $apply_metaroles
197             );
198              
199             # Add class roles
200 17         36175 Moose::Util::apply_all_roles($args{for_class},@{$apply_roles});
  17         128  
201              
202             # Init plugins
203 17         21269 foreach my $plugin_class (@{$plugins}) {
  17         73  
204 15 50       176 if ($plugin_class->can('init_plugin')) {
205 0         0 $plugin_class->init_plugin($args{for_class});
206             }
207             }
208              
209             # Return meta
210 17         130 my $meta = $args{for_class}->meta;
211              
212 17         525 return $meta;
213             }
214              
215             sub command_short_description($) {
216 18     18 0 467 my ( $meta, $description ) = @_;
217 18         792 return $meta->command_short_description($description);
218             }
219              
220             sub command_long_description($) {
221 10     10 0 13975 my ( $meta, $description ) = @_;
222 10         424 return $meta->command_long_description($description);
223             }
224              
225             sub command_usage($) {
226 0     0 0   my ( $meta, $usage ) = @_;
227 0           return $meta->command_usage($usage);
228             }
229              
230             *app_description = \&command_long_description;
231             *app_usage = \&command_usage;
232              
233             sub command_strict($) {
234 0     0 0   my ( $meta, $value ) = @_;
235 0           return $meta->command_strict($value);
236             }
237              
238             1;